◆ Sapport for developers API reference Error catalog OpenAPI
Sections

Webhooks

Methods in this section: 8. All methods

MethodPathDescriptionScopesStatus
GET/webhooksList subscriptionswebhooks:manageAvailable
POST/webhooksCreate a subscriptionwebhooks:manageAvailable
GET/webhooks/{id}Get a subscriptionwebhooks:manageAvailable
PATCH/webhooks/{id}Update a subscriptionwebhooks:manageAvailable
DELETE/webhooks/{id}Delete a subscriptionwebhooks:manageAvailable
POST/webhooks/{id}/rotate-secretRotate the secretwebhooks:manageAvailable
POST/webhooks/{id}/testSend a test eventwebhooks:manageAvailable
GET/webhooks/{id}/deliveriesDelivery logwebhooks:manageAvailable
GET /webhooks Available

#List subscriptions

The subscriptions of this integration (at most 10). The signing secret is not returned.

Scopes
webhooks:manage
Rate limit
read
Idempotency
not required
Successful response
200 A page of subscriptions.

Response body

FieldTypeDescription
dataarray<Webhook>
required
next_cursorstring
required, may be null
Cursor of the next page; null — the list is exhausted. Valid for 24 hours.

Examples

Request
curl -X GET 'https://wfacademy.org/api/public/v1/webhooks' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY"
Response 200
{
  "data": [
    {
      "id": "EXAMPLE_ID",
      "url": "https://example.com/hooks/sapport",
      "events": [
        null
      ],
      "include_pii": false,
      "description": null,
      "status": "active",
      "created_at": "2026-10-11T09:00:00Z",
      "updated_at": "2026-10-11T09:00:00Z",
      "secret_rotated_at": null,
      "previous_secret_expires_at": null
    }
  ],
  "next_cursor": "EXAMPLE_CURSOR"
}
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing

POST /webhooks Available

#Create a subscription

Creates an event subscription. The signing secret is shown once, in this response. The URL goes through SSRF protection; include_pii: true is allowed only for lead.*, contact.* and conversation.* events.

Scopes
webhooks:manage
Rate limit
write
Idempotency
Idempotency-Key is required
Successful response
201 The subscription with its secret.

Parameters

FieldTypeDescription
Idempotency-Keystring
required
In: header. A unique string (usually a UUID v4), new for every new operation. A retry with the same key and body yields the same result.

Request body Subscription parameters.

FieldTypeDescription
urlstring
required
Receiving URL: https, port 443, a host name (not an IP), no redirects.
eventsarray<string>
required
Event types: an exact type or a family pattern "family.*". Available types: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring.
include_piiboolean
optional
Full payload with personal data; only for lead.*, contact.* and conversation.* events. Default false.
descriptionstring
optional, may be null
A note for yourself, up to 200 characters.

Response body

FieldTypeDescription
idstring
required
Subscription id.
urlstring
required
Receiving URL: https, port 443, a host name (not an IP), no redirects.
eventsarray<string>
required
Event types: an exact type or a family pattern "family.*". Available types: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring.
include_piiboolean
required
Full payload with personal data; only for lead.*, contact.* and conversation.* events. Default false.
descriptionstring
required, may be null
A note for yourself, up to 200 characters.
statusstring
required
active — deliveries flow; paused — suspended.
Values: active paused
created_atstring
required
ISO 8601 UTC.
updated_atstring
required
ISO 8601 UTC.
secret_rotated_atstring
required, may be null
Time of the last secret rotation; null — never rotated.
previous_secret_expires_atstring
required, may be null
While the rotation window (24 hours) is open — when the previous secret stops working; otherwise null.
secretstring
required, may be null
The signing secret: shown ONCE, in the creation or rotation response. On an idempotent replay of the request — null: keep the secret from the first response.

Examples

Request
curl -X POST 'https://wfacademy.org/api/public/v1/webhooks' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY" \
  -H 'Idempotency-Key: '"$(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://example.com/hooks/sapport",
  "events": [
    "string"
  ],
  "include_pii": false,
  "description": "string"
}'
Response 201
{
  "id": "EXAMPLE_ID",
  "url": "https://example.com/hooks/sapport",
  "events": [
    "string"
  ],
  "include_pii": false,
  "description": "string",
  "status": "active",
  "created_at": "2026-10-11T09:00:00Z",
  "updated_at": "2026-10-11T09:00:00Z",
  "secret_rotated_at": "2026-10-11T09:00:00Z",
  "previous_secret_expires_at": "2026-10-11T09:00:00Z",
  "secret": "string"
}
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing pii_transfer_not_allowed bad_request validation_failed payload_too_large idempotency_key_required idempotency_conflict operation_in_progress invalid_state

GET /webhooks/{id} Available

#Get a subscription

The subscription without its secret.

Scopes
webhooks:manage
Rate limit
read
Idempotency
not required
Successful response
200 The subscription.

Parameters

FieldTypeDescription
idstring
required
In: path. Subscription id.

Response body

FieldTypeDescription
idstring
required
Subscription id.
urlstring
required
Receiving URL: https, port 443, a host name (not an IP), no redirects.
eventsarray<string>
required
Event types: an exact type or a family pattern "family.*". Available types: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring.
include_piiboolean
required
Full payload with personal data; only for lead.*, contact.* and conversation.* events. Default false.
descriptionstring
required, may be null
A note for yourself, up to 200 characters.
statusstring
required
active — deliveries flow; paused — suspended.
Values: active paused
created_atstring
required
ISO 8601 UTC.
updated_atstring
required
ISO 8601 UTC.
secret_rotated_atstring
required, may be null
Time of the last secret rotation; null — never rotated.
previous_secret_expires_atstring
required, may be null
While the rotation window (24 hours) is open — when the previous secret stops working; otherwise null.

Examples

Request
curl -X GET 'https://wfacademy.org/api/public/v1/webhooks/EXAMPLE_ID' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY"
Response 200
{
  "id": "EXAMPLE_ID",
  "url": "https://example.com/hooks/sapport",
  "events": [
    "string"
  ],
  "include_pii": false,
  "description": "string",
  "status": "active",
  "created_at": "2026-10-11T09:00:00Z",
  "updated_at": "2026-10-11T09:00:00Z",
  "secret_rotated_at": "2026-10-11T09:00:00Z",
  "previous_secret_expires_at": "2026-10-11T09:00:00Z"
}
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing not_found

PATCH /webhooks/{id} Available

#Update a subscription

Changes the URL, events, note, status (active or paused) and include_pii. Pass at least one field.

Scopes
webhooks:manage
Rate limit
write
Idempotency
not required
Successful response
200 The subscription after the update.

Parameters

FieldTypeDescription
idstring
required
In: path. Subscription id.

Request body The fields to change.

FieldTypeDescription
urlstring
optional
Receiving URL: https, port 443, a host name (not an IP), no redirects.
eventsarray<string>
optional
Event types: an exact type or a family pattern "family.*". Available types: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring.
include_piiboolean
optional
Full payload with personal data; only for lead.*, contact.* and conversation.* events. Default false.
descriptionstring
optional, may be null
A note for yourself, up to 200 characters.
statusstring
optional
Pause or resume deliveries.
Values: active paused

Response body

FieldTypeDescription
idstring
required
Subscription id.
urlstring
required
Receiving URL: https, port 443, a host name (not an IP), no redirects.
eventsarray<string>
required
Event types: an exact type or a family pattern "family.*". Available types: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring.
include_piiboolean
required
Full payload with personal data; only for lead.*, contact.* and conversation.* events. Default false.
descriptionstring
required, may be null
A note for yourself, up to 200 characters.
statusstring
required
active — deliveries flow; paused — suspended.
Values: active paused
created_atstring
required
ISO 8601 UTC.
updated_atstring
required
ISO 8601 UTC.
secret_rotated_atstring
required, may be null
Time of the last secret rotation; null — never rotated.
previous_secret_expires_atstring
required, may be null
While the rotation window (24 hours) is open — when the previous secret stops working; otherwise null.

Examples

Request
curl -X PATCH 'https://wfacademy.org/api/public/v1/webhooks/EXAMPLE_ID' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://example.com/hooks/sapport",
  "events": [
    "string"
  ],
  "include_pii": false,
  "description": "string",
  "status": "active"
}'
Response 200
{
  "id": "EXAMPLE_ID",
  "url": "https://example.com/hooks/sapport",
  "events": [
    "string"
  ],
  "include_pii": false,
  "description": "string",
  "status": "active",
  "created_at": "2026-10-11T09:00:00Z",
  "updated_at": "2026-10-11T09:00:00Z",
  "secret_rotated_at": "2026-10-11T09:00:00Z",
  "previous_secret_expires_at": "2026-10-11T09:00:00Z"
}
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing pii_transfer_not_allowed not_found bad_request validation_failed payload_too_large

DELETE /webhooks/{id} Available

#Delete a subscription

Deletes the subscription together with its delivery log. Deleting again returns not_found.

Scopes
webhooks:manage
Rate limit
write
Idempotency
not required
Successful response
204 The subscription is deleted; no body.

Parameters

FieldTypeDescription
idstring
required
In: path. Subscription id.

Examples

Request
curl -X DELETE 'https://wfacademy.org/api/public/v1/webhooks/EXAMPLE_ID' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY"
Response 204
HTTP/1.1 204
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing not_found

POST /webhooks/{id}/rotate-secret Available

#Rotate the secret

Issues a new secret (shown once). Both secrets are valid for 24 hours and every delivery is signed with both.

Scopes
webhooks:manage
Rate limit
write
Idempotency
Idempotency-Key is required
Successful response
200 The subscription with the new secret.

Parameters

FieldTypeDescription
idstring
required
In: path. Subscription id.
Idempotency-Keystring
required
In: header. A unique string (usually a UUID v4), new for every new operation. A retry with the same key and body yields the same result.

Response body

FieldTypeDescription
idstring
required
Subscription id.
urlstring
required
Receiving URL: https, port 443, a host name (not an IP), no redirects.
eventsarray<string>
required
Event types: an exact type or a family pattern "family.*". Available types: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring.
include_piiboolean
required
Full payload with personal data; only for lead.*, contact.* and conversation.* events. Default false.
descriptionstring
required, may be null
A note for yourself, up to 200 characters.
statusstring
required
active — deliveries flow; paused — suspended.
Values: active paused
created_atstring
required
ISO 8601 UTC.
updated_atstring
required
ISO 8601 UTC.
secret_rotated_atstring
required, may be null
Time of the last secret rotation; null — never rotated.
previous_secret_expires_atstring
required, may be null
While the rotation window (24 hours) is open — when the previous secret stops working; otherwise null.
secretstring
required, may be null
The signing secret: shown ONCE, in the creation or rotation response. On an idempotent replay of the request — null: keep the secret from the first response.

Examples

Request
curl -X POST 'https://wfacademy.org/api/public/v1/webhooks/EXAMPLE_ID/rotate-secret' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY" \
  -H 'Idempotency-Key: '"$(uuidgen)"
Response 200
{
  "id": "EXAMPLE_ID",
  "url": "https://example.com/hooks/sapport",
  "events": [
    "string"
  ],
  "include_pii": false,
  "description": "string",
  "status": "active",
  "created_at": "2026-10-11T09:00:00Z",
  "updated_at": "2026-10-11T09:00:00Z",
  "secret_rotated_at": "2026-10-11T09:00:00Z",
  "previous_secret_expires_at": "2026-10-11T09:00:00Z",
  "secret": "string"
}
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing not_found idempotency_key_required idempotency_conflict operation_in_progress

POST /webhooks/{id}/test Available

#Send a test event

Queues a webhook.test event (livemode: false) for this subscription only. The subscription must be active.

Scopes
webhooks:manage
Rate limit
write
Idempotency
Idempotency-Key is required
Successful response
202 The event is queued.

Parameters

FieldTypeDescription
idstring
required
In: path. Subscription id.
Idempotency-Keystring
required
In: header. A unique string (usually a UUID v4), new for every new operation. A retry with the same key and body yields the same result.

Response body

FieldTypeDescription
event_idstring
required, may be null
The test event id.
typestring
required
statusstring
required
The event is queued; it goes out on the next delivery run (within a minute).

Examples

Request
curl -X POST 'https://wfacademy.org/api/public/v1/webhooks/EXAMPLE_ID/test' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY" \
  -H 'Idempotency-Key: '"$(uuidgen)"
Response 202
{
  "event_id": "EXAMPLE_ID",
  "type": "string",
  "status": "string"
}
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing not_found invalid_state idempotency_key_required idempotency_conflict operation_in_progress

GET /webhooks/{id}/deliveries Available

#Delivery log

Delivery attempts of the subscription, newest first; kept for 30 days.

Scopes
webhooks:manage
Rate limit
read
Idempotency
not required
Successful response
200 A page of the log.

Parameters

FieldTypeDescription
idstring
required
In: path. Subscription id.
limitinteger
optional
In: query. Page size: 1 to 100, default 25.
cursorstring
optional
In: query. The next_cursor value from the previous response. Valid for 24 hours; start over when filters change.
statestring
optional
In: query. Filter by delivery state.

Response body

FieldTypeDescription
dataarray<WebhookDelivery>
required
next_cursorstring
required, may be null
Cursor of the next page; null — the list is exhausted. Valid for 24 hours.

Examples

Request
curl -X GET 'https://wfacademy.org/api/public/v1/webhooks/EXAMPLE_ID/deliveries' \
  -H 'Authorization: Bearer '"$SAPPORT_API_KEY"
Response 200
{
  "data": [
    {
      "id": "EXAMPLE_ID",
      "event_id": "EXAMPLE_ID",
      "state": "pending",
      "attempt": 0,
      "status_code": null,
      "duration_ms": null,
      "error": null,
      "next_attempt_at": null,
      "delivered_at": null,
      "created_at": "2026-10-11T09:00:00Z"
    }
  ],
  "next_cursor": "EXAMPLE_CURSOR"
}
Error example
{
  "type": "https://wfacademy.org/developers/errors#scope_missing",
  "title": "Scope is missing",
  "status": 403,
  "code": "scope_missing",
  "detail": "EXAMPLE",
  "request_id": "req_EXAMPLE"
}

Examples are illustrative: the key in them is a placeholder (EXAMPLE), field values are made up.

Possible errors

invalid_api_key wrong_cell integration_inactive tenant_inactive ip_not_allowed feature_not_in_plan rate_limited wallet_suspended service_unavailable internal_error scope_missing not_found validation_failed