Skip to content
Cirrus home
Sign in

Webhooks

Signed HTTPS calls to your server when orders, trades or positions change.

Read the guide first

List webhooks #

GET /v1/postbacks scope read

The signed-in user's webhooks (never their secrets), oldest first.

More about this

Event bodies are described in the document's webhooks section (order_update, trade, account_alert, positions, ping; components WebhookOrderUpdate, WebhookTrade, WebhookAccountAlert, WebhookPositions, WebhookPing), with how deliveries are signed and retried.

Errors

HTTP Code When
401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

GET
curl "https://api.cirrus.trade/v1/postbacks" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": [
    {
      "id": "pb_01m5yb0gy8qwqm4gbe8tg61nhf",
      "url": "http://127.0.0.1:61319/hooks/orders",
      "events": [
        "order_update",
        "trade"
      ],
      "accounts": [
        "P1"
      ],
      "description": "Order desk",
      "enabled": true,
      "disabled_reason": null,
      "disabled_at": null,
      "consecutive_failures": 0,
      "last_success_at": null,
      "last_failure_at": null,
      "previous_secret_expires_at": null,
      "secret_rotated_at": null,
      "created_at": "2026-10-27T09:28:08.904Z",
      "updated_at": "2026-10-27T09:28:08.904Z"
    }
  ],
  "error": null
}

Create a webhook #

POST /v1/postbacks scope webhooks

Registers an HTTPS receiver for the chosen events (optionally only for some of the user's accounts).

More about this

The signing secret is in this response only: store it now. A user may have at most 5 webhooks. Event bodies are described in the document's webhooks section (order_update, trade, account_alert, positions, ping; components WebhookOrderUpdate, WebhookTrade, WebhookAccountAlert, WebhookPositions, WebhookPing), with how deliveries are signed and retried.

Only the account holder can create webhooks: signed in themselves, or with one of their API keys holding the webhooks scope (never a partner app).

Body fields

  • url string required

    The receiver: an https:// URL on a public host (private, loopback and link-local addresses are refused).

  • events string[] required

    Events to send, at least one: order_update, trade, account_alert, positions (ping cannot be subscribed to).

    One of: order_update, trade, account_alert, positions, ping

  • accounts string[] | null

    Only these of the user's accounts (non-empty, the user's own); leave out or null for every account, including ones added later.

  • description string | null

    A note for the owner, at most 200 characters.

  • trigger_updates boolean

    true also sends trigger_update (a v2 trigger of the user changed; see the document's webhooks section). Off unless set (also later with PATCH).

Errors

HTTP Code When
400 malformed_json

The body is not JSON, or does not fit the request shape (unknown or missing fields, wrong types).

401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 own_session_required

Credentials can only be created from the user's own signed-in session.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

409 webhook_limit_reached

The webhook limit is reached; delete one first.

422 invalid_request

The request is well-formed but not valid; field names the input.

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

POST
curl -X POST "https://api.cirrus.trade/v1/postbacks" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "http://127.0.0.1:61319/hooks/orders",
    "events": [
      "order_update",
      "trade"
    ],
    "accounts": [
      "P1"
    ],
    "description": "Order desk"
  }'
Response · 201
{
  "status": "success",
  "data": {
    "id": "pb_01m5yb0gy8qwqm4gbe8tg61nhf",
    "url": "http://127.0.0.1:61319/hooks/orders",
    "events": [
      "order_update",
      "trade"
    ],
    "accounts": [
      "P1"
    ],
    "description": "Order desk",
    "enabled": true,
    "disabled_reason": null,
    "disabled_at": null,
    "consecutive_failures": 0,
    "last_success_at": null,
    "last_failure_at": null,
    "previous_secret_expires_at": null,
    "secret_rotated_at": null,
    "created_at": "2026-10-27T09:28:08.904Z",
    "updated_at": "2026-10-27T09:28:08.904Z",
    "secret": "whsec_lW1M6I7AW+mbrgsUJkWvnLgrevwb/FI4DX+XFigSAuU=",
    "note": "Store the secret now: it is not shown again."
  },
  "error": null
}

Get a webhook #

GET /v1/postbacks/{id} scope read

One webhook (never its secret): its settings and delivery health.

Parameters

  • id path · string required

    The webhook's id.

Errors

HTTP Code When
401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

404 webhook_not_found

No webhook with this id for the caller.

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

GET
curl "https://api.cirrus.trade/v1/postbacks/<id>" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "id": "pb_01m5yb0gy8qwqm4gbe8tg61nhf",
    "url": "http://127.0.0.1:61319/hooks/orders",
    "events": [
      "order_update",
      "trade"
    ],
    "accounts": [
      "P1"
    ],
    "description": "Order desk",
    "enabled": true,
    "disabled_reason": null,
    "disabled_at": null,
    "consecutive_failures": 0,
    "last_success_at": null,
    "last_failure_at": null,
    "previous_secret_expires_at": null,
    "secret_rotated_at": null,
    "created_at": "2026-10-27T09:28:08.904Z",
    "updated_at": "2026-10-27T09:28:08.904Z"
  },
  "error": null
}

Change a webhook #

PATCH /v1/postbacks/{id} scope webhooks

Changes only the fields sent: url, events, accounts (null = every account), description (null removes it) and enabled.

More about this

enabled: true turns a webhook back on, also after it was turned off for failing (its failure count starts again). An empty body changes nothing.

Only the account holder, signed in themselves, can change webhooks.

Parameters

  • id path · string required

    The webhook's id.

Body fields

  • url string | null

    A new receiver URL (same rules as on creation).

  • events string[] | null

    A new event list (replaces the old one; at least one).

    One of: order_update, trade, account_alert, positions, ping

  • accounts string[] | null

    A new account list; null goes back to every account.

  • description string | null

    A new note; null or empty removes it.

  • enabled boolean | null

    false turns deliveries off; true turns them back on (also after the webhook was turned off for failing).

  • trigger_updates boolean | null

    true also sends trigger_update (a v2 trigger of the user changed; see the document's webhooks section); false stops it. A new webhook starts without it unless created with it.

Errors

HTTP Code When
400 malformed_json

The body is not JSON, or does not fit the request shape (unknown or missing fields, wrong types).

401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 own_session_required

Credentials can only be created from the user's own signed-in session.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

404 webhook_not_found

No webhook with this id for the caller.

422 invalid_request

The request is well-formed but not valid; field names the input.

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

PATCH
curl -X PATCH "https://api.cirrus.trade/v1/postbacks/<id>" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      "order_update",
      "trade",
      "positions"
    ],
    "accounts": null,
    "enabled": false
  }'
Response · 200
{
  "status": "success",
  "data": {
    "id": "pb_01m5yb0gy8qwqm4gbe8tg61nhf",
    "url": "http://127.0.0.1:61319/hooks/orders",
    "events": [
      "order_update",
      "trade",
      "positions"
    ],
    "accounts": null,
    "description": "Order desk",
    "enabled": false,
    "disabled_reason": "disabled_by_user",
    "disabled_at": "2026-10-27T09:28:08.908Z",
    "consecutive_failures": 0,
    "last_success_at": null,
    "last_failure_at": null,
    "previous_secret_expires_at": null,
    "secret_rotated_at": null,
    "created_at": "2026-10-27T09:28:08.904Z",
    "updated_at": "2026-10-27T09:28:08.908Z"
  },
  "error": null
}

Delete a webhook #

DELETE /v1/postbacks/{id} scope webhooks

Deletes the webhook; nothing more is sent to it.

More about this

Only the account holder, signed in themselves, can delete webhooks.

Parameters

  • id path · string required

    The webhook's id.

Errors

HTTP Code When
401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 own_session_required

Credentials can only be created from the user's own signed-in session.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

404 webhook_not_found

No webhook with this id for the caller.

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

DELETE
curl -X DELETE "https://api.cirrus.trade/v1/postbacks/<id>" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "id": "pb_01m3pgps5ctt0rdj2zq50g1dad",
    "deleted": true
  },
  "error": null
}

Rotate a webhook's secret #

POST /v1/postbacks/{id}/rotate-secret scope webhooks

Issues a new signing secret, shown only in this response.

More about this

For 24 hours deliveries are signed with both the new and the previous secret (one signature each in webhook-signature), so the receiver can switch without losing any. Only the account holder, signed in themselves, can rotate secrets.

Parameters

  • id path · string required

    The webhook's id.

Errors

HTTP Code When
401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 own_session_required

Credentials can only be created from the user's own signed-in session.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

404 webhook_not_found

No webhook with this id for the caller.

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

POST
curl -X POST "https://api.cirrus.trade/v1/postbacks/<id>/rotate-secret" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "id": "pb_01m3pgps5ctt0rdj2zq50g1dad",
    "url": "http://127.0.0.1:63815/hooks/alerts",
    "events": [
      "account_alert"
    ],
    "accounts": null,
    "description": null,
    "enabled": true,
    "disabled_reason": null,
    "disabled_at": null,
    "consecutive_failures": 0,
    "last_success_at": null,
    "last_failure_at": null,
    "previous_secret_expires_at": "2026-09-30T12:02:21.998Z",
    "secret_rotated_at": "2026-09-29T12:02:21.998Z",
    "created_at": "2026-09-29T12:02:21.996Z",
    "updated_at": "2026-09-29T12:02:21.998Z",
    "secret": "whsec_sesnDRH8eVMm3rJqiKEp0+QVa3wcLxUqhsXlqR2dqeQ=",
    "note": "Store the secret now: it is not shown again."
  },
  "error": null
}

Send a test delivery #

POST /v1/postbacks/{id}/test scope webhooks

Sends one signed ping event (body: component WebhookPing) to the webhook now, even when it is turned off, and says how the receiver answered.

More about this

One attempt, no retry; it is logged with the webhook's deliveries. Only the account holder, signed in themselves, can send tests.

Parameters

  • id path · string required

    The webhook's id.

Errors

HTTP Code When
401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 own_session_required

Credentials can only be created from the user's own signed-in session.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

404 webhook_not_found

No webhook with this id for the caller.

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

POST
curl -X POST "https://api.cirrus.trade/v1/postbacks/<id>/test" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "event_id": "evt_cc2f23548b726e8a6a8bf980be542540",
    "delivered": true,
    "status_code": 200,
    "duration_ms": 0,
    "error_kind": null
  },
  "error": null
}

List a webhook's delivery attempts #

GET /v1/postbacks/{id}/deliveries scope read

Every delivery attempt of the last 7 days, newest first: event, attempt number, outcome, the receiver's status and timing (never the body).

More about this

Page with limit and cursor.

Parameters

  • id path · string required

    The webhook's id.

  • limit query · integer

    Page size, 1-200 (default 50).

  • cursor query · string

    next_cursor of the previous page.

Errors

HTTP Code When
400 invalid_query

The query string does not fit the route's parameters.

401 unauthorized

No credential, or the credential is invalid, expired or revoked.

403 forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

404 webhook_not_found

No webhook with this id for the caller.

422 invalid_request

The request is well-formed but not valid; field names the input.

429 rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503 webhooks_disabled

Webhooks are not enabled on this server.

503 service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

GET
curl "https://api.cirrus.trade/v1/postbacks/<id>/deliveries" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "deliveries": [
      {
        "id": "01M3PGPS5DF35SYE2PF2KKBM9V",
        "event_id": "evt_cc2f23548b726e8a6a8bf980be542540",
        "type": "ping",
        "attempt": 1,
        "outcome": "delivered",
        "status_code": 200,
        "duration_ms": 0,
        "error_kind": null,
        "at": "2026-09-29T12:02:21.997Z"
      }
    ],
    "next_cursor": null
  },
  "error": null
}