RMO

Webhook Subscriptions

Manage which events get delivered, where they go, and the signing secret used to authenticate them. Create, list, update, pause, rotate, revoke.

One subscription = one URL + a set of events. A tenant can have many. Each subscription has its own signing secret (the whsec_…), its own failure counter, and its own pause/revoke state. After 50 consecutive failed deliveries the subscription auto-pauses.

Create

POST/v1/webhook-subscriptions

Register a new subscription. The response includes the signing secret — it’s returned only once. Persist it securely; you’ll need it to verify every delivery.

FieldTypeDescription
url requiredstring(uri)Your https endpoint. Must be reachable from the public internet. http://localhost permitted for local dev only.
events requiredarray<string>One or more event types: authorization.approved, authorization.declined, authorization.captured, authorization.reversed.
description optionalstring(256)Free-text label for your own bookkeeping.
curl https://api.rmous.org/v1/webhook-subscriptions \
  -H "X-API-Key: pk_test_publicsandbox_2026" \
  -H "Authorization: Bearer sk_test_publicsandbox_2026_anyone_can_use_this" \
  -H "Idempotency-Key: sub-prod-2026-05-14" \
  -H "Content-Type: application/json" \
  -d '{
    "url":         "https://your-app.example.com/webhooks/rmo",
    "events":      ["authorization.approved", "authorization.captured"],
    "description": "Production receiver"
  }'

# Response (201) - secret returned ONCE:
{
  "id":           "sub_abc123xyz456",
  "url":          "https://your-app.example.com/webhooks/rmo",
  "events":       ["authorization.approved", "authorization.captured"],
  "description":  "Production receiver",
  "secret":       "whsec_5OuMr0xLNgPjV3qbWfHk2tT8eC0aA1nIcRzZyXdY",
  "secretLast4":  "XdY",
  "status":       "active",
  "failureCount": 0,
  "created":      "2026-05-14T17:00:00Z"
}
Save the secret now. It will never appear again in any API response. To replace a lost or compromised secret, use POST /rotate-secret below — but that invalidates the old one immediately.

List

GET/v1/webhook-subscriptions

Cursor-paginated list of your tenant’s subscriptions.

QueryDefaultDescription
limit251–100.
starting_afterCursor: pass the last id from the previous page.
statusFilter to active, paused, or revoked.
curl "https://api.rmous.org/v1/webhook-subscriptions?limit=25&status=active" \
  -H "X-API-Key: $RMO_API_KEY" \
  -H "Authorization: Bearer $RMO_BEARER"

# Response:
{
  "data": [
    { "id": "sub_abc123...", "url": ..., "events": [...], "status": "active", ... }
  ],
  "hasMore": false
}

Read one

GET/v1/webhook-subscriptions/{id}

Single subscription by ID. secret is never included — you only ever get secretLast4 for identification.

Update

PATCH/v1/webhook-subscriptions/{id}

Change any of: url, events, description, or status. Use status: "paused" to temporarily stop deliveries; status: "active" resumes (and resets the consecutive-failure counter to 0). Use DELETE to revoke.

FieldTypeDescription
url optionalstring(uri)Replace the delivery URL.
events optionalarray<string>Replace the full set (not additive).
description optionalstringReplace label.
status optionalenumactive or paused.
# Add a new event type and update the URL
curl -X PATCH https://api.rmous.org/v1/webhook-subscriptions/sub_abc123... \
  -H "X-API-Key: $RMO_API_KEY" \
  -H "Authorization: Bearer $RMO_BEARER" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://your-app.example.com/v2/webhooks/rmo",
    "events": ["authorization.approved", "authorization.captured", "authorization.reversed"]
  }'

Rotate secret

POST/v1/webhook-subscriptions/{id}/rotate-secret

Mint a new signing secret and replace the current one in a single mutation. The new secret is returned once. Deliveries enqueued from this moment on use the new key — switch your verification code over before any new events fire.

curl -X POST https://api.rmous.org/v1/webhook-subscriptions/sub_abc123.../rotate-secret \
  -H "X-API-Key: $RMO_API_KEY" \
  -H "Authorization: Bearer $RMO_BEARER"

# Response (200) - the secret field is the NEW one:
{
  "id":          "sub_abc123...",
  "secret":      "whsec_NEW_VALUE...",
  "secretLast4": "vAL",
  ...
}

Revoke (soft delete)

DELETE/v1/webhook-subscriptions/{id}

Flips status to revoked. The worker stops delivering new events to this subscription. Already-pending retries are still attempted — revoke only blocks new enqueues.

curl -X DELETE https://api.rmous.org/v1/webhook-subscriptions/sub_abc123... \
  -H "X-API-Key: $RMO_API_KEY" \
  -H "Authorization: Bearer $RMO_BEARER"

# Response: { "id": "sub_abc123...", "revoked": true }

Inspect deliveries

GET/v1/webhook-subscriptions/{id}/deliveries

Recent delivery attempts for debugging. Filter by event type and paginate with starting_after (going backwards in time).

curl "https://api.rmous.org/v1/webhook-subscriptions/sub_abc123.../deliveries?limit=10&event=authorization.captured" \
  -H "X-API-Key: $RMO_API_KEY" \
  -H "Authorization: Bearer $RMO_BEARER"

# Response:
{
  "data": [
    {
      "id":            "del_NNN...",
      "event":         "authorization.captured",
      "url":           "https://your-app.example.com/webhooks/rmo",
      "attempt":       1,
      "status":        "Webhook Delivered",
      "responseCode":  200,
      "error":         null,
      "scheduledAt":   "2026-05-14T17:01:33Z",
      "deliveredAt":   "2026-05-14T17:01:33Z",
      "nextRetryAt":   null
    }
  ],
  "hasMore": false
}

Useful states: Webhook Pending · Webhook Delivered · Webhook Failed · Webhook Retry Exhausted.

Where to next

Webhook signatures & verification → Error reference → OpenAPI spec →
Start typing to search across all pages