Swapping webhook delivery roles
Swapping webhook delivery roles
Contents
- Overview
- Version-specific information
- Permissions and Authentication
- Headers
- HTTP Parameters
- Example request
- Example response JSON
- Possible error responses
Overview
- Call name: swap-webhook-delivery-roles
- Endpoint URL: https://{API hostname}/internal/swap-webhook-delivery-roles
- Request methods: PUT
- Request Content-Type: application/x-www-form-urlencoded or application/json
- Response Content-Type: application/json
- Auth required: yes
This endpoint exchanges the primary and standby delivery roles of a chain's verification webhook pair, so the webhook that was standing by becomes the one that sends and the previous sender becomes the backup. See backup email provider for how a pair works.
It is a separate endpoint because the same change cannot be made with two alter-webhook calls: whichever call went first would leave the event with either two primaries or none, and both states are rejected. This endpoint swaps both roles in one step, so the pair is never left in an invalid state.
Both a live primary and a live standby must exist for the event. If either is missing there is no pair to swap and the call fails with error 495, webhook_not_found, rather than promoting a lone webhook.
Version-specific information
The following version-specific changes apply to this endpoint. See the versioning page for more details.
| Version | Change details |
|---|---|
| N/A | N/A |
Permissions and Authentication
This API call requires a valid Spaaza session. See the authentication page for more details. The session can be as follows:
- Admin authentication: The performing user needs to be logged in and have
write accessto the chain to which the webhooks belong. The performing user is recorded inlast_updated_byon both webhooks.
Headers
The following headers can/must be passed to the API call:
| Parameter | Description |
|---|---|
| N/A | N/A |
HTTP Parameters
The following HTTP parameters can be passed to the API:
| Parameter | Description |
|---|---|
| chain_id | (integer, mandatory) The ID of the chain that owns the webhook pair. |
| event_name | (string, mandatory) The verification event whose pair is being swapped: email_verification_otp, email_verification_deeplink or phone_number_verification. |
Example request
PUT https://{API hostname}/internal/swap-webhook-delivery-roles
{
"chain_id": 1743,
"event_name": "email_verification_otp"
}
Example response JSON
The endpoint returns JSON showing both webhooks with their new roles, the new primary first. An example response is shown below:
{
"result": {
"code": 1,
"status": "ok"
},
"results": {
"webhooks": [
{
"active": true,
"applies_legacy_hmac": false,
"campaign_id": null,
"created_date": "2026-08-20T10:05:00+00:00",
"delivery_role": "primary",
"event_name": "email_verification_otp",
"event_trigger": null,
"filter": null,
"id": 1235,
"identifier_key": null,
"identifier_secret": null,
"is_default": false,
"last_modified_date": "2026-09-08T09:30:00+00:00",
"last_updated_by": {
"name": "Admin User",
"user_id": 213112
},
"payload_spaaza_api_version": "1.4.8",
"send_from": null,
"task_id": null,
"type": "ses",
"url": null,
"webhook_signature": null
},
{
"active": true,
"applies_legacy_hmac": false,
"campaign_id": null,
"created_date": "2026-08-20T10:00:00+00:00",
"delivery_role": "standby",
"event_name": "email_verification_otp",
"event_trigger": null,
"filter": null,
"id": 1234,
"identifier_key": "spaaza-verification",
"identifier_secret": "****",
"is_default": false,
"last_modified_date": "2026-09-08T09:30:00+00:00",
"last_updated_by": {
"name": "Admin User",
"user_id": 213112
},
"payload_spaaza_api_version": "1.4.8",
"send_from": "noreply@example.com",
"task_id": null,
"type": "smtp",
"url": "smtp://mail.example.com:587",
"webhook_signature": null
}
],
"result_type": "swap-webhook-delivery-roles"
}
}
Possible error responses
| Code | Name | Description | HTTP Status |
|---|---|---|---|
| 3 | http_vars_missing | Required parameter is missing (chain_id or event_name) | 400 |
| 6 | no_valid_session | No valid session key provided or session has expired | 401 |
| 68 | permission_denied_or_non_existent | User has insufficient permissions or the chain does not exist | 403 |
| 493 | webhook_event_name_invalid | The event_name is not one of the verification events | 400 |
| 495 | webhook_not_found | The chain does not have both a live primary and a live standby webhook for the event | 400 |
| 562 | webhook_delivery_role_conflict | The swapped pair would not be valid, for example because a webhook's type does not deliver the event | 400 |