Docs / API reference

HTTP API reference.

What the Python and TypeScript SDKs post on the wire. Production base URL is https://mesedi-api.fly.dev. Local development is http://localhost:8080. If you're using one of the SDKs, you never need this page; it's here for non-Python, non-Node stacks and for self-hosters who want to verify what their agents are sending.

Authentication

Every protected endpoint requires a bearer token. Mint one in the dashboard under API Keys. The raw key is shown once at mint time; we cannot recover it for you later.

Authorization: Bearer mesedi_sk_...

Requests without Authorization: Bearer are rejected with 401. Requests with an unrecognized key are rejected with 401. Requests with a project_id in the body that does not match the auth-context project are rejected with 403.

Schema versioning

Every request should include X-Mesedi-Schema-Version: 1. The backend policy:

  • Header missing: accepted (assumed current version, soft-mode for bring-up flows and curl smoke tests).
  • Header equals 1: accepted.
  • Header present and not 1: rejected with 400 and a message naming the supported version(s).

When v2 ships, the policy tightens to missing → 400 so unversioned callers surface loudly instead of silently coasting on a stale wire format.

POST /executions

Record the start of an agent execution.

curl -X POST https://mesedi-api.fly.dev/executions \
  -H "Authorization: Bearer $MESEDI_API_KEY" \
  -H "X-Mesedi-Schema-Version: 1" \
  -H "Content-Type: application/json" \
  -d '{
    "execution_id": "exec-001",
    "status": "started",
    "sdk_language": "python",
    "sdk_version": "0.1.0"
  }'

PATCH /executions/{id}

Update an execution. Used by the SDKs to mark completion or crash.

# completed
curl -X PATCH https://mesedi-api.fly.dev/executions/exec-001 \
  -H "Authorization: Bearer $MESEDI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "completed",
    "duration_ms": 1234,
    "total_tokens_in": 50,
    "total_tokens_out": 200
  }'

# crashed
curl -X PATCH https://mesedi-api.fly.dev/executions/exec-001 \
  -H "Authorization: Bearer $MESEDI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "crashed",
    "crash_signature": "sha256:abcdef...",
    "duration_ms": 412
  }'

POST /events

Ship a batch of events for an existing execution. The SDKs batch up to ~100 events every few hundred milliseconds.

curl -X POST https://mesedi-api.fly.dev/events \
  -H "Authorization: Bearer $MESEDI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "event_id": "evt-001",
      "execution_id": "exec-001",
      "event_type": "llm_call",
      "sequence": 1,
      "timestamp": "2026-05-24T14:00:00Z",
      "payload": {
        "model": "claude-opus-4-6",
        "tokens_in": 12,
        "tokens_out": 80
      }
    }
  ]'

Common event_type values: llm_call, tool_call, checkpoint, validator_check.

Rate limiting

Every authenticated request consumes 1 token from a per-project bucket. Defaults: burst capacity 100 tokens, refill 10 tokens/second. A well-behaved SDK (events buffered client-side, flushed in batches) never sees a 429. An infinite-loop agent without backoff hits 429 within ~10 seconds.

Every response (200 and 429 alike) includes:

  • X-RateLimit-Limit: bucket capacity
  • X-RateLimit-Remaining: tokens left after this request
  • X-RateLimit-Reset: Unix timestamp when the bucket refills to full

On 429, AWS-style Retry-After: 1 is also set.

Webhook delivery contract

When a failure-class detector fires for the first time in a project (or after a configured cooldown), Mesedi POSTs a JSON payload to each configured webhook URL. See Webhooks in the dashboard to configure URLs.

POST <your webhook url>
Content-Type: application/json
X-Mesedi-Signature: sha256=...
X-Mesedi-Event: failure_group.first_occurrence

{
  "event": "failure_group.first_occurrence",
  "project_id": "proj_...",
  "failure_group": {
    "id": "fg_...",
    "class": "prompt_injection",
    "signature": "...",
    "first_seen_at": "2026-05-24T14:00:00Z",
    "severity": "high"
  },
  "playbook_url": "https://mesedi.vercel.app/app/playbooks/prompt_injection"
}

The signature is HMAC-SHA256 of the raw request body keyed by the webhook secret shown to you at create time. Slack and Discord URLs are auto-detected and receive native attachments / embeds; plain URLs get the JSON above.

GET /health

Public, no auth. Used by the status page at mesedi-ai.github.io/status.

curl https://mesedi-api.fly.dev/health
# {"ok":true,"service":"mesedi-backend","version":"...","time":"..."}

What's next?

Failure classes and playbooks explains what each detector is looking for in the telemetry you ship.

Self-hosting guide covers running the Go backend behind your own infrastructure.