Skip to content

Webhooks

View as Markdown

Get events (new messages, delivery updates) pushed to your server.

Endpoints

List event types

gethttps://api.saei.automize.sa/v1/event_types
  • Scope: webhooks:read
  • Works in test mode

Every event you can subscribe an endpoint to.

Response fields200
  • object"list"required
  • dataarray<EventType>required
    Child fields (4)
    • object"event_type"required
    • typestringrequired
    • object_typestringoptional
    • descriptionstringrequired
  • has_morebooleanrequired
  • next_cursorstring | nullrequired
Try it
curl -X GET https://api.saei.automize.sa/v1/event_types \
  -H "Authorization: Bearer $API_KEY"
Response

The event types.

{
  "object": "list",
  "data": [
    {
      "object": "event_type",
      "type": "message.delivered",
      "object_type": "string",
      "description": "string"
    }
  ],
  "has_more": false,
  "next_cursor": "string"
}

Retry a delivery now

posthttps://api.saei.automize.sa/v1/webhook_deliveries/{id}/retry
  • Scope: webhooks:write
  • Works in test mode

Sends the same event again (same webhook-id, fresh signature), e.g. after you fixed your server.

Path parameters

  • idstringrequired

    The object's id.

Response fields202
  • idstringrequired
  • object"webhook_delivery"required
  • livemodebooleanrequired
  • webhook_endpoint_idstringrequired
  • event_idstringrequired
  • event_typestringrequired
  • statusstringrequired

    failed will be retried at next_attempt_at; dead will not be retried again.

    One ofpendingsucceededfaileddead

  • attemptsintegerrequired
  • http_statusinteger | nulloptional
  • duration_msinteger | nulloptional
  • response_snippetstring | nulloptional
  • last_errorstring | nulloptional
  • next_attempt_atstring | nulloptional
  • delivered_atstring | nulloptional
  • created_atstring | nulloptional
  • payloadobjectoptional

    The body of every webhook request. data.object is exactly the resource the REST API returns (e.g. a message).

    Child fields (8)
    • idstringrequired

      Event id, also sent as the webhook-id header. The same on every retry, so use it to ignore duplicates.

    • object"event"required
    • typestringrequired
    • versionstringrequired

      Payload version. Fields are only ever added within a version.

    • created_atstringrequired
    • livemodebooleanrequired
    • workspace_idstringrequired
    • dataobjectrequired
      Child fields (2)
      • objectobjectrequired
      • previous_attributesobjectoptional

        The values that changed, as they were before, when known.

Errors this can return1
Try it
curl -X POST https://api.saei.automize.sa/v1/webhook_deliveries/del_01j9x3k2m4n5p6q7r8s9t0v1w2/retry \
  -H "Authorization: Bearer $API_KEY"
Response

Queued.

{
  "id": "del_01j9x3k2m4n5p6q7r8s9t0v1w2",
  "object": "webhook_delivery",
  "livemode": false,
  "webhook_endpoint_id": "string",
  "event_id": "string",
  "event_type": "string",
  "status": "pending",
  "attempts": 0,
  "http_status": 0,
  "duration_ms": 0,
  "response_snippet": "string",
  "last_error": "string",
  "next_attempt_at": "2026-10-01T09:30:00Z",
  "delivered_at": "2026-10-01T09:30:00Z",
  "created_at": "2026-10-01T09:30:00Z",
  "payload": {
    "id": "evt_01j9x3k2m4n5p6q7r8s9t0v1w2",
    "object": "event",
    "type": "message.delivered",
    "version": "2",
    "created_at": "2026-10-01T09:30:00Z",
    "livemode": false,
    "workspace_id": "ws_12",
    "data": {
      "object": {},
      "previous_attributes": {}
    }
  }
}

List webhook endpoints

gethttps://api.saei.automize.sa/v1/webhook_endpoints
  • Scope: webhooks:read
  • Works in test mode

The endpoints in the key's mode (live keys see live endpoints, test keys test endpoints).

Response fields200
  • object"list"required
  • dataarray<WebhookEndpoint>required
    Child fields (12)
    • idstringrequired
    • object"webhook_endpoint"required
    • livemodebooleanrequired

      Live endpoints get live events; test endpoints get test-mode events. Never both.

    • urlstringrequired
    • descriptionstring | nulloptional
    • enabled_eventsarray<string>required

      Event types to send, a whole group such as contact.*, or ["*"] for all.

    • statusstringrequired

      auto_disabled after 3 days of failed deliveries or a 410 Gone answer.

      One ofenableddisabledauto_disabled

    • disabled_reasonstring | nulloptional
    • secret_previewstringoptional
    • secretstringoptional

      The signing secret (whsec_…). Returned only when the endpoint is created or its secret rotated. Store it now.

    • created_atstring | nullrequired
    • updated_atstring | nulloptional
  • has_morebooleanrequired
  • next_cursorstring | nullrequired
Errors this can return1
Try it
curl -X GET https://api.saei.automize.sa/v1/webhook_endpoints \
  -H "Authorization: Bearer $API_KEY"
Response

The endpoints.

{
  "object": "list",
  "data": [
    {
      "id": "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
      "object": "webhook_endpoint",
      "livemode": false,
      "url": "string",
      "description": "string",
      "enabled_events": [
        "string"
      ],
      "status": "enabled",
      "disabled_reason": "string",
      "secret_preview": "string",
      "secret": "string",
      "created_at": "2026-10-01T09:30:00Z",
      "updated_at": "2026-10-01T09:30:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": "string"
}

Add a webhook endpoint

posthttps://api.saei.automize.sa/v1/webhook_endpoints
  • Scope: webhooks:write
  • Works in test mode
  • Accepts Idempotency-Key

We will POST each subscribed event to url as JSON, signed with the Standard Webhooks scheme. The response includes the signing secret once: store it to verify signatures.

In production the URL must be https:// and publicly reachable. Up to 10 endpoints per workspace.

An event carries the same data its read endpoint returns, so each event family needs that read scope: message.* needs messages:read, contact.* contacts:read, conversation.* conversations:read, campaign.* campaigns:read, flow.* flows:read, template.* templates:read. ["*"] needs all of them. The same check applies when you change the URL or events of an endpoint.

Headers

  • Idempotency-Keystringoptional

    Any unique string (a UUID is ideal). Retrying with the same key and body returns the first response instead of acting twice. Remembered for 24 hours.

Request body

  • urlstringrequired

    Where to send events.

  • enabled_eventsarray<string>required

    Event types from GET /v1/event_types, a whole group such as contact.*, or ["*"] for all.

  • descriptionstringoptional
Response fields201
  • idstringrequired
  • object"webhook_endpoint"required
  • livemodebooleanrequired

    Live endpoints get live events; test endpoints get test-mode events. Never both.

  • urlstringrequired
  • descriptionstring | nulloptional
  • enabled_eventsarray<string>required

    Event types to send, a whole group such as contact.*, or ["*"] for all.

  • statusstringrequired

    auto_disabled after 3 days of failed deliveries or a 410 Gone answer.

    One ofenableddisabledauto_disabled

  • disabled_reasonstring | nulloptional
  • secret_previewstringoptional
  • secretstringoptional

    The signing secret (whsec_…). Returned only when the endpoint is created or its secret rotated. Store it now.

  • created_atstring | nullrequired
  • updated_atstring | nulloptional
Errors this can return6
Try it
curl -X POST https://api.saei.automize.sa/v1/webhook_endpoints \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/webhooks/whatsapp",
  "enabled_events": [
    "message.received",
    "message.delivered",
    "message.read",
    "message.failed"
  ],
  "description": "Order system"
}'
Response

Created. `secret` is shown only now.

{
  "id": "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
  "object": "webhook_endpoint",
  "livemode": true,
  "url": "https://example.com/webhooks/whatsapp",
  "description": "Order system",
  "enabled_events": [
    "message.received",
    "message.delivered",
    "message.read",
    "message.failed"
  ],
  "status": "enabled",
  "disabled_reason": null,
  "secret_preview": "whsec_…K3x=",
  "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw/kNEBw0UXK3x=",
  "created_at": "2026-10-01T09:30:00Z",
  "updated_at": "2026-10-01T09:30:00Z"
}

Get a webhook endpoint

gethttps://api.saei.automize.sa/v1/webhook_endpoints/{id}
  • Scope: webhooks:read
  • Works in test mode

Path parameters

  • idstringrequired

    The object's id.

Response fields200
  • idstringrequired
  • object"webhook_endpoint"required
  • livemodebooleanrequired

    Live endpoints get live events; test endpoints get test-mode events. Never both.

  • urlstringrequired
  • descriptionstring | nulloptional
  • enabled_eventsarray<string>required

    Event types to send, a whole group such as contact.*, or ["*"] for all.

  • statusstringrequired

    auto_disabled after 3 days of failed deliveries or a 410 Gone answer.

    One ofenableddisabledauto_disabled

  • disabled_reasonstring | nulloptional
  • secret_previewstringoptional
  • secretstringoptional

    The signing secret (whsec_…). Returned only when the endpoint is created or its secret rotated. Store it now.

  • created_atstring | nullrequired
  • updated_atstring | nulloptional
Errors this can return1
Try it
curl -X GET https://api.saei.automize.sa/v1/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2 \
  -H "Authorization: Bearer $API_KEY"
Response

The endpoint.

{
  "id": "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
  "object": "webhook_endpoint",
  "livemode": false,
  "url": "string",
  "description": "string",
  "enabled_events": [
    "string"
  ],
  "status": "enabled",
  "disabled_reason": "string",
  "secret_preview": "string",
  "secret": "string",
  "created_at": "2026-10-01T09:30:00Z",
  "updated_at": "2026-10-01T09:30:00Z"
}

Update a webhook endpoint

patchhttps://api.saei.automize.sa/v1/webhook_endpoints/{id}
  • Scope: webhooks:write
  • Works in test mode

Change the URL or events, or pause it with "disabled": true. Re-enabling clears the failure count.

Path parameters

  • idstringrequired

    The object's id.

Request body

  • urlstringoptional
  • enabled_eventsarray<string>optional
  • descriptionstring | nulloptional
  • disabledbooleanoptional
Response fields200
  • idstringrequired
  • object"webhook_endpoint"required
  • livemodebooleanrequired

    Live endpoints get live events; test endpoints get test-mode events. Never both.

  • urlstringrequired
  • descriptionstring | nulloptional
  • enabled_eventsarray<string>required

    Event types to send, a whole group such as contact.*, or ["*"] for all.

  • statusstringrequired

    auto_disabled after 3 days of failed deliveries or a 410 Gone answer.

    One ofenableddisabledauto_disabled

  • disabled_reasonstring | nulloptional
  • secret_previewstringoptional
  • secretstringoptional

    The signing secret (whsec_…). Returned only when the endpoint is created or its secret rotated. Store it now.

  • created_atstring | nullrequired
  • updated_atstring | nulloptional
Errors this can return4
Try it
curl -X PATCH https://api.saei.automize.sa/v1/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled_events": [
    "*"
  ]
}'
Response

The updated endpoint.

{
  "id": "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
  "object": "webhook_endpoint",
  "livemode": false,
  "url": "string",
  "description": "string",
  "enabled_events": [
    "string"
  ],
  "status": "enabled",
  "disabled_reason": "string",
  "secret_preview": "string",
  "secret": "string",
  "created_at": "2026-10-01T09:30:00Z",
  "updated_at": "2026-10-01T09:30:00Z"
}

Delete a webhook endpoint

deletehttps://api.saei.automize.sa/v1/webhook_endpoints/{id}
  • Scope: webhooks:write
  • Works in test mode

Stops all deliveries to it, including pending retries.

Path parameters

  • idstringrequired

    The object's id.

Response fields200
  • idstringrequired
  • object"webhook_endpoint"required
  • deletedtruerequired
Errors this can return1
Try it
curl -X DELETE https://api.saei.automize.sa/v1/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2 \
  -H "Authorization: Bearer $API_KEY"
Response

Deleted.

{
  "id": "string",
  "object": "webhook_endpoint",
  "deleted": true
}

List deliveries

gethttps://api.saei.automize.sa/v1/webhook_endpoints/{id}/deliveries
  • Scope: webhooks:read
  • Works in test mode

Every attempt to deliver an event to this endpoint, newest first, with the HTTP status your server answered.

Path parameters

  • idstringrequired

    The object's id.

Query parameters

  • limitintegeroptional

    How many objects to return, 1 to 100.

  • cursorstringoptional

    The next_cursor from the previous page.

  • statusstringoptional

    Only deliveries in this state.

    One ofpendingsucceededfaileddead

Response fields200
  • object"list"required
  • dataarray<WebhookDelivery>required
    Child fields (16)
    • idstringrequired
    • object"webhook_delivery"required
    • livemodebooleanrequired
    • webhook_endpoint_idstringrequired
    • event_idstringrequired
    • event_typestringrequired
    • statusstringrequired

      failed will be retried at next_attempt_at; dead will not be retried again.

      One ofpendingsucceededfaileddead

    • attemptsintegerrequired
    • http_statusinteger | nulloptional
    • duration_msinteger | nulloptional
    • response_snippetstring | nulloptional
    • last_errorstring | nulloptional
    • next_attempt_atstring | nulloptional
    • delivered_atstring | nulloptional
    • created_atstring | nulloptional
    • payloadobjectoptional

      The body of every webhook request. data.object is exactly the resource the REST API returns (e.g. a message).

      Child fields (8)
      • idstringrequired

        Event id, also sent as the webhook-id header. The same on every retry, so use it to ignore duplicates.

      • object"event"required
      • typestringrequired
      • versionstringrequired

        Payload version. Fields are only ever added within a version.

      • created_atstringrequired
      • livemodebooleanrequired
      • workspace_idstringrequired
      • dataobjectrequired
        Child fields (2)
        • objectobjectrequired
        • previous_attributesobjectoptional

          The values that changed, as they were before, when known.

  • has_morebooleanrequired
  • next_cursorstring | nullrequired
Errors this can return1
Try it
curl -X GET https://api.saei.automize.sa/v1/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2/deliveries \
  -H "Authorization: Bearer $API_KEY"
Response

A page of deliveries.

{
  "object": "list",
  "data": [
    {
      "id": "del_01j9x3k2m4n5p6q7r8s9t0v1w2",
      "object": "webhook_delivery",
      "livemode": false,
      "webhook_endpoint_id": "string",
      "event_id": "string",
      "event_type": "string",
      "status": "pending",
      "attempts": 0,
      "http_status": 0,
      "duration_ms": 0,
      "response_snippet": "string",
      "last_error": "string",
      "next_attempt_at": "2026-10-01T09:30:00Z",
      "delivered_at": "2026-10-01T09:30:00Z",
      "created_at": "2026-10-01T09:30:00Z",
      "payload": {
        "id": "evt_01j9x3k2m4n5p6q7r8s9t0v1w2",
        "object": "event",
        "type": "message.delivered",
        "version": "2",
        "created_at": "2026-10-01T09:30:00Z",
        "livemode": false,
        "workspace_id": "ws_12",
        "data": {
          "object": {},
          "previous_attributes": {}
        }
      }
    }
  ],
  "has_more": false,
  "next_cursor": "string"
}

Rotate the signing secret

posthttps://api.saei.automize.sa/v1/webhook_endpoints/{id}/rotate_secret
  • Scope: webhooks:write
  • Works in test mode

Returns a new secret. For 24 hours every event is signed with both the old and the new secret, so you can deploy the new one without missing events.

Path parameters

  • idstringrequired

    The object's id.

Response fields200
  • idstringrequired
  • object"webhook_endpoint"required
  • livemodebooleanrequired

    Live endpoints get live events; test endpoints get test-mode events. Never both.

  • urlstringrequired
  • descriptionstring | nulloptional
  • enabled_eventsarray<string>required

    Event types to send, a whole group such as contact.*, or ["*"] for all.

  • statusstringrequired

    auto_disabled after 3 days of failed deliveries or a 410 Gone answer.

    One ofenableddisabledauto_disabled

  • disabled_reasonstring | nulloptional
  • secret_previewstringoptional
  • secretstringoptional

    The signing secret (whsec_…). Returned only when the endpoint is created or its secret rotated. Store it now.

  • created_atstring | nullrequired
  • updated_atstring | nulloptional
Errors this can return1
Try it
curl -X POST https://api.saei.automize.sa/v1/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2/rotate_secret \
  -H "Authorization: Bearer $API_KEY"
Response

The endpoint, with its new secret.

{
  "id": "we_01j9x3k2m4n5p6q7r8s9t0v1w2",
  "object": "webhook_endpoint",
  "livemode": false,
  "url": "string",
  "description": "string",
  "enabled_events": [
    "string"
  ],
  "status": "enabled",
  "disabled_reason": "string",
  "secret_preview": "string",
  "secret": "string",
  "created_at": "2026-10-01T09:30:00Z",
  "updated_at": "2026-10-01T09:30:00Z"
}

Send a test event

posthttps://api.saei.automize.sa/v1/webhook_endpoints/{id}/test
  • Scope: webhooks:write
  • Works in test mode

Sends a signed webhook.test event to this endpoint only. Check the delivery with the deliveries endpoint.

Path parameters

  • idstringrequired

    The object's id.

Response fields202
  • idstringrequired
  • object"webhook_delivery"required
  • livemodebooleanrequired
  • webhook_endpoint_idstringrequired
  • event_idstringrequired
  • event_typestringrequired
  • statusstringrequired

    failed will be retried at next_attempt_at; dead will not be retried again.

    One ofpendingsucceededfaileddead

  • attemptsintegerrequired
  • http_statusinteger | nulloptional
  • duration_msinteger | nulloptional
  • response_snippetstring | nulloptional
  • last_errorstring | nulloptional
  • next_attempt_atstring | nulloptional
  • delivered_atstring | nulloptional
  • created_atstring | nulloptional
  • payloadobjectoptional

    The body of every webhook request. data.object is exactly the resource the REST API returns (e.g. a message).

    Child fields (8)
    • idstringrequired

      Event id, also sent as the webhook-id header. The same on every retry, so use it to ignore duplicates.

    • object"event"required
    • typestringrequired
    • versionstringrequired

      Payload version. Fields are only ever added within a version.

    • created_atstringrequired
    • livemodebooleanrequired
    • workspace_idstringrequired
    • dataobjectrequired
      Child fields (2)
      • objectobjectrequired
      • previous_attributesobjectoptional

        The values that changed, as they were before, when known.

Errors this can return2
Try it
curl -X POST https://api.saei.automize.sa/v1/webhook_endpoints/we_01j9x3k2m4n5p6q7r8s9t0v1w2/test \
  -H "Authorization: Bearer $API_KEY"
Response

The test event was queued.

{
  "id": "del_01j9x3k2m4n5p6q7r8s9t0v1w2",
  "object": "webhook_delivery",
  "livemode": false,
  "webhook_endpoint_id": "string",
  "event_id": "string",
  "event_type": "string",
  "status": "pending",
  "attempts": 0,
  "http_status": 0,
  "duration_ms": 0,
  "response_snippet": "string",
  "last_error": "string",
  "next_attempt_at": "2026-10-01T09:30:00Z",
  "delivered_at": "2026-10-01T09:30:00Z",
  "created_at": "2026-10-01T09:30:00Z",
  "payload": {
    "id": "evt_01j9x3k2m4n5p6q7r8s9t0v1w2",
    "object": "event",
    "type": "message.delivered",
    "version": "2",
    "created_at": "2026-10-01T09:30:00Z",
    "livemode": false,
    "workspace_id": "ws_12",
    "data": {
      "object": {},
      "previous_attributes": {}
    }
  }
}