Skip to main content
DeveloperAPI Reference

Webhooks API

Manage NimbusOS webhook endpoints programmatically -- create, update, delete, list, and inspect delivery logs via REST API.

8 min read
Updated April 23, 2026
1,700 words

The Webhooks API lets you manage outbound webhook endpoints programmatically. Create new endpoints, update subscriptions, inspect delivery logs, and rotate signing secrets without using the UI. This is the companion API to the Webhooks integration documentation, which covers the payload format, signature verification, and retry behavior.

Base URL and Authentication

https://getnimbusos.com/api/v1/webhooks/

Bearer token authentication. JWT or API key with the webhooks:read and webhooks:write scopes.

Webhook Endpoint Object

{
  "id": "wh_abc123",
  "workspace_id": "ws_xyz789",
  "name": "Data pipeline ingestion",
  "url": "https://data-pipeline.internal/webhooks/nimbus",
  "active": true,
  "event_subscriptions": [
    "contact.created",
    "contact.updated",
    "email.replied",
    "campaign.auto_paused"
  ],
  "signing_secret_preview": "whsec_...abc",
  "custom_headers": {
    "X-Source": "nimbusos"
  },
  "health_status": "healthy",
  "last_delivery_at": "2026-04-23T14:00:00Z",
  "delivery_success_rate_24h": 0.998,
  "total_deliveries_30d": 128450,
  "failed_deliveries_30d": 142,
  "created_at": "2026-01-15T10:00:00Z",
  "updated_at": "2026-04-01T09:00:00Z"
}

Note: signing_secret_preview shows only the prefix. The full signing secret is returned once at creation and is never retrievable again. Store it in a secrets manager when you create the endpoint.

List Endpoints

GET /api/v1/webhooks/

Returns all webhook endpoints in the workspace. No pagination needed; the 20 endpoint limit keeps the list small.

Get Endpoint

GET /api/v1/webhooks/wh_abc123/

Returns the single endpoint object.

Create Endpoint

POST /api/v1/webhooks/
Content-Type: application/json

{
  "name": "Data pipeline ingestion",
  "url": "https://data-pipeline.internal/webhooks/nimbus",
  "event_subscriptions": [
    "contact.created",
    "contact.updated",
    "email.replied"
  ],
  "custom_headers": {
    "X-Source": "nimbusos"
  }
}

Response includes the full endpoint object plus signing_secret (only on create):

{
  "id": "wh_abc123",
  ...
  "signing_secret": "whsec_long_random_string_you_need_to_save"
}

The signing_secret is the HMAC key your endpoint uses to verify signatures. Save it; it cannot be retrieved later.

On create, NimbusOS sends a test event to the URL. If the URL does not respond with 2xx within 30 seconds, the create succeeds but the endpoint is marked unhealthy from the start.

Update Endpoint

PATCH /api/v1/webhooks/wh_abc123/
Content-Type: application/json

{
  "event_subscriptions": [
    "contact.created",
    "contact.updated",
    "email.replied",
    "email.bounced"
  ],
  "active": true
}

Common update patterns:

  • Adding or removing event subscriptions
  • Pausing the endpoint (active: false) without deleting
  • Updating the URL after infrastructure changes
  • Updating custom headers

Rotate Signing Secret

POST /api/v1/webhooks/wh_abc123/rotate-secret/

Generates a new signing secret and returns it. The old secret is invalidated immediately. In-flight events signed with the old secret will fail verification.

For rolling rotation, the typical pattern:

  1. Update your endpoint to accept either the old or the new secret.
  2. Rotate via API.
  3. Remove support for the old secret from your endpoint after 1 hour.

Delete Endpoint

DELETE /api/v1/webhooks/wh_abc123/

Removes the endpoint. No retries after delete. History is retained per the delivery log retention (30 days).

Test an Endpoint

POST /api/v1/webhooks/wh_abc123/test/
Content-Type: application/json

{
  "event_type": "email.replied"
}

Sends a synthetic event to the endpoint with the specified event type. The synthetic event has well-known test data and is flagged with "test": true in the payload.

Response includes the delivery outcome (status code, latency, error if any).

List Delivery Log

GET /api/v1/webhooks/wh_abc123/deliveries/?status=failed&page_size=50

Query parameters:

  • status: success, failed, pending
  • event_type: filter to a specific event
  • delivered_after, delivered_before: ISO 8601 timestamps

Response:

{
  "data": [
    {
      "id": "whd_xyz",
      "event_id": "evt_abc",
      "event_type": "email.replied",
      "delivered_at": "2026-04-23T14:32:11Z",
      "status": "failed",
      "status_code": 500,
      "response_body": "Internal Server Error",
      "latency_ms": 2345,
      "retry_count": 3,
      "next_retry_at": "2026-04-23T15:32:11Z"
    },
    ...
  ],
  "meta": { "next_cursor": "...", "has_more": true }
}

Delivery logs retain for 30 days.

Retry a Failed Delivery

POST /api/v1/webhooks/wh_abc123/deliveries/whd_xyz/retry/

Fires the event immediately. Useful after you have fixed an issue on your endpoint and want to replay a specific event.

Replay a Range

POST /api/v1/webhooks/wh_abc123/replay/
Content-Type: application/json

{
  "event_types": ["email.replied", "email.bounced"],
  "from": "2026-04-20T00:00:00Z",
  "to": "2026-04-23T00:00:00Z"
}

Replays all matching events in the range. Replayed events carry "X-Nimbus-Replay: true" header. Your endpoint should handle replay idempotently.

Replay is rate-limited to prevent accidental floods. Very large replays are rejected; split into smaller ranges.

Event Type Catalog

GET /api/v1/webhooks/event-types/

Returns the full list of available event types with schema for each. Useful for dynamic integrations that adapt to new event types as they are added.

Response shape:

{
  "data": [
    {
      "event_type": "email.replied",
      "category": "send",
      "description": "An inbound reply arrived and was classified.",
      "payload_schema": { ... JSON schema ... }
    },
    ...
  ]
}

Health Status

Each endpoint has a live health_status:

  • healthy: recent deliveries succeeding
  • degraded: recent failures above 10 percent
  • failed: continuous failures for over 1 hour
  • paused: manually disabled

Health automatically transitions based on delivery outcomes. A failed endpoint that starts responding again returns to healthy after 10 consecutive successful deliveries.

Bulk Operations

Create multiple endpoints

No bulk create endpoint. Create one at a time.

Subscribe multiple endpoints to the same event

No batch subscription. Create each endpoint with its own subscriptions.

Permission Model

Webhook management requires specific scopes.

  • webhooks:read: list and get endpoints, inspect delivery logs.
  • webhooks:write: create, update, delete, rotate secrets.

Admin-tier users have both scopes implicitly. API keys need explicit scope.

Common Integration Patterns

Pattern 1: Set up integrations programmatically

Infrastructure as code. Terraform or similar provisions webhook endpoints via API as part of your deploy pipeline.

resp = requests.post(
    "https://getnimbusos.com/api/v1/webhooks/",
    headers={"Authorization": "Bearer " + API_KEY},
    json={
        "name": "Data pipeline prod",
        "url": "https://data-pipeline.internal/webhooks/nimbus",
        "event_subscriptions": ["contact.created", "email.replied"],
    },
)
signing_secret = resp.json()["signing_secret"]
# Save to secrets manager
save_to_vault("nimbus-webhook-signing-secret", signing_secret)

Pattern 2: Monitor health

Scheduled job queries endpoint health. Alerts if any endpoint is degraded or failed.

endpoints = requests.get(
    "https://getnimbusos.com/api/v1/webhooks/",
    headers={"Authorization": "Bearer " + API_KEY},
).json()

unhealthy = [e for e in endpoints["data"] if e["health_status"] != "healthy"]
if unhealthy:
    alert(unhealthy)

Pattern 3: Programmatic replay after outage

Your endpoint was down for 3 hours. Script replays the missed events after the endpoint is back.

requests.post(
    f"https://getnimbusos.com/api/v1/webhooks/{webhook_id}/replay/",
    headers={"Authorization": "Bearer " + API_KEY},
    json={
        "from": outage_start,
        "to": outage_end,
    },
)

Pattern 4: Rotate signing secrets on schedule

Quarterly rotation of signing secrets. Script rotates each endpoint, updates the downstream secret in the secrets manager, and verifies delivery still succeeds.

Troubleshooting

"Endpoint created but no events are arriving"

Check active: true on the endpoint. Also confirm the event subscriptions include events that are actually happening (for example, subscribing to email.replied when no replies have arrived yet is the common case).

"Delivery log shows 500 errors on my endpoint"

Check your endpoint logs. NimbusOS records the response body (first 2 KB) in the delivery log for debugging.

"Can I change the URL without losing subscriptions?"

Yes, PATCH the URL. Existing subscriptions remain. Deliveries immediately redirect to the new URL.

"Rotating the secret broke my endpoint"

Expected during rotation. Either use rolling rotation (support both secrets briefly) or rotate during a maintenance window.

Frequently Asked Questions

Is there a maximum number of events per endpoint?

Per delivery payload, one event. Some workflows prefer batched delivery; this is not supported by default. Enterprise tier offers batched delivery on request.

Can I subscribe to all events?

Not via a wildcard. Subscribe to specific types. The event catalog is stable; new event types are added over time but do not break existing subscriptions.

What is the maximum body size I can return?

2 MB. Larger responses are truncated in the delivery log.

Does the API support filtering events by content?

Not at the subscription level. Filter on your endpoint. If filtering cost is an issue, consider a middleware layer that filters before routing to downstream systems.

Useful next pages after this one: Webhooks for the payload format and verification, Authentication for the API key and scope model, and Rate Limits for the request throughput envelope.

Related articles

Still stuck?

Our team answers every support ticket. If the answer is not in the docs, open a ticket and we will write the missing page.