← All docs

Public API

This documents the HTTP endpoints Mergen's runtime already accepts authenticated calls on today. It exists because the website listed "Public API" as a shipped capability while nothing described these endpoints as a product surface: the routes were real, just undocumented as a set. This page closes that gap by describing what's actually callable, not by promising a separate, packaged API product that doesn't exist yet. See What this is not (yet) at the bottom before you build production tooling against it.

For the full local runtime (every route, mergen-server internals), see CLI_REFERENCE.md. This page covers only the routes meant to be called by an external system with an API key or admin secret, not the local dashboard/IDE-extension traffic, which talks to 127.0.0.1 without one.


Authentication: two independent layers

Which one applies depends on deployment mode and route. Both are described in full in the main README's Security section; this is the short version for API callers specifically.

1. x-mergen-secret: admin mutation guard (local and cloud). Every mutating route, including POST /incident, requires this header to match ~/.mergen/secret (auto-generated on first run) or MERGEN_ADMIN_SECRET if you've set one. This exists so that an AI agent with plain filesystem access on the machine can't forge an admin action by hitting the HTTP API directly: it is not a "public" credential to hand out to arbitrary integrations.

curl -s http://127.0.0.1:3000/incident \
  -H "x-mergen-secret: $(cat ~/.mergen/secret)" \
  -H 'Content-Type: application/json' \
  -d '{"title":"api is down","service":"api"}'

2. x-api-key: tenant-scoped cloud auth (MERGEN_CLOUD_MODE=true only). On the multi-tenant cloud deployment, the routes below are additionally wrapped in tenant authentication, which validates a plain-text key against its SHA-256 hash, enforces a per-key rate limit (default 1000 events/minute), and sets req.tenantId so every read and write is isolated to your organization's data; see the Deployment boundary note in the main README for exactly which routes are tenant-partitioned versus process-global.

curl -s https://your-cloud-instance/incident \
  -H 'x-api-key: mrgn_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"title":"api is down","service":"api"}'

Getting a key today is an operator action, not self-service. POST /api-keys (below) itself requires x-mergen-secret; there is no public sign-up flow that mints a key without admin access to the instance. This is intentional: keys are provisioned by whoever runs the cloud instance, the same way mergen-server config set requires the same secret.

curl -s -X POST https://your-cloud-instance/api-keys \
  -H "x-mergen-secret: ..." -H 'Content-Type: application/json' \
  -d '{"tenantId":"acme-corp","label":"ci-pipeline"}'
# → { "ok": true, "id": "...", "key": "mrgn_live_...", "note": "Store this key securely; it will not be shown again." }

GET /api-keys (list, no plain text) and DELETE /api-keys/:id (revoke) are also admin-secret-guarded.


Endpoints

Capability policy

Capability policy resolves configurable Gate A rules through the fixed precedence immutable rule floor > organization policy > developer preference > built-in default. All mutating endpoints require x-mergen-secret; when RBAC is configured they also require an admin identity in x-mergen-member. Agent-scoped tokens cannot call these endpoints.

  • GET|POST|DELETE /capability-policy/preferences reads or changes the local developer policy.
  • GET|POST|DELETE /capability-policy/organization reads or changes the separately signed organization policy floor. POST accepts { "posture": "custom", "capabilities": { "git.force_push": "ask" } }. Invalid or externally replaced policy files fail closed; runtime changes must go through this admin API.
  • GET /capability-policy/effective returns the resolved action for every capability-tagged rule plus developerPolicySet and organizationPolicySet.

The same organization document is distributed with shared enterprise rules as the optional organizationCapabilityPolicy member of the versioned policy. GET /policies/sync signs and ETags the combined document for self-hosted fleets; cloud drafts/publishes store both under one version; POST /policies/import validates and applies both before a cloud sync marker or acknowledgment advances. Legacy documents without the member preserve the current local organization floor, while an explicit null clears it.

CLI administrators can use mergen-server policy organization [show], policy organization set <capability> <allow|ask|block>, policy organization posture <balanced|strict>, and policy organization clear. Add --member <id> when local RBAC is configured.

Incident intake: POST /incident

Feeds the incident autopilot, which is off by default (MERGEN_AUTOPILOT) and not part of agent governance: nothing here affects a PASS / HOLD / BLOCK verdict. It runs the same triage pipeline as a PagerDuty webhook, for any monitoring tool that can POST JSON.

curl -X POST http://127.0.0.1:3000/incident \
  -H "x-mergen-secret: $(cat ~/.mergen/secret)" \
  -H 'Content-Type: application/json' \
  -d '{"title":"api is down","service":"api"}'
# → { "ok": true, "pid": "<uuid>", "message": "Autopilot started" }

Edit-time change gate: POST /gate/evaluate-edit

Runs the deterministic diff-content detectors (secret introduction, deleted tests, auth-bypass, CI-check removal, permission/config weakening) against a single pending file edit, before the write lands. Returns pass, hold or block plus the findings. This is the endpoint the IDE Edit/Write/MultiEdit hooks and the Cursor/VS Code self-heal integrations call. Each detector has its own rung (MERGEN_EDIT_GATE_DETECTOR_MODES, <id>:shadow|hold|enforce); MERGEN_EDIT_GATE_MODE is only an on/off kill switch (default on).

Telemetry ingest: POST /ingest, POST /v1/traces, POST /v1/logs

/ingest accepts Mergen's native event shapes (console, network, terminal, diagnostic). /v1/traces and /v1/logs speak OTLP over HTTP, JSON encoding only; see the main README's Backend instrumentation section for the exact OTEL_EXPORTER_OTLP_PROTOCOL=http/json requirement most SDKs need set explicitly. /v1/metrics returns 200 but stores nothing today.

Service topology: GET /service-graph, GET /route-reachability

Read-only views of the live service dependency graph built from observed OTLP spans, the same data GET /topology renders as an interactive D3 graph. /route-reachability narrows this to which routes are provably reachable, used to suppress hypotheses about unreachable code paths during diagnosis.


What this is not (yet)

Being straightforward about maturity, since the whole point of this page is to stop overclaiming:

  • No stable versioning scheme. There is no /v1/-prefixed convention for Mergen's own endpoints (OTLP's /v1/traces path is OTLP's own spec, not ours); a breaking change to a route's shape is not yet fenced by a version number.
  • No official client SDKs, beyond the one-line Node auto-instrumentation (import 'mergen-server/sdk/node.js'). Every example above is a raw curl call.
  • No published, guaranteed rate-limit contract beyond the per-API-key default (1000 events/minute, configurable per key at creation).
  • No OpenAPI/Swagger spec. This document is hand-maintained against the route source files, not generated, unlike CONFIGURATION.md, which a census test keeps in sync with the code automatically. If this page drifts from the routes, the running server's behavior is the source of truth.

Last updated October 31, 2026