API

Webhooks

The webhooks API sends project events to an external HTTPS endpoint. Each delivery is signed, retried when appropriate, and identified for deduplication.

Create a subscription

POST /v1/projects/{project}/webhooks
{
  "name": "Run status sink",
  "url": "https://hooks.example.com/mobius/run-status",
  "events": ["run.completed", "run.failed"],
  "enabled": true
}

The create response includes the signing secret once:

{
  "id": "<webhook-id>",
  "name": "Run status sink",
  "signing_secret": "<one-time-signing-secret>"
}

Store it immediately. Later reads return webhook metadata without the secret.

An empty event list subscribes to every project event. Wildcards such as run.* subscribe to an event family. Prefer narrow subscriptions so a receiver does not spend most of its time discarding events.

Verify deliveries

Use the SDK verification helper with the raw request body and signing secret. The helper checks the HMAC signature, timestamp drift, and replay identity.

Every receiver should:

  1. Verify the signature before parsing trusted fields.
  2. Reject timestamps more than five minutes away from the receiver clock.
  3. Deduplicate by delivery_id; retries reuse the same ID.

Test and inspect

POST /v1/projects/{project}/webhooks/{webhook_id}/ping
GET /v1/projects/{project}/webhooks/{webhook_id}/deliveries

Ping the receiver before relying on the subscription. If an event appears in Mobius but not in the destination, inspect delivery attempts and response codes first.

Network errors, 408, 429, and server errors retry up to 10 times. Other client errors are permanent because changing nothing and sending the same bad request again would not help. Each attempt has a 10-second timeout.

Rotate the signing secret

POST /v1/projects/{project}/webhooks/{webhook_id}/secret/rotate

Rotation returns a new secret once. Update the receiver before discarding the old secret according to your deployment procedure.

Next