Configure Webhooks
Manage your webhook endpoint, subscribed events, and signing secret. either through the Developer Console UI or via the API directly.
Get Current Configuration
/v1/webhook/configRequired permission: webhook:get
Returns the active webhook configuration for the current environment. The signing secret is never returned in full. only a masked preview is shown.
Response
| Field | Type | Description |
|---|---|---|
webhookUrl | String? | Your registered callback URL. null if not yet configured. |
webhookEvents | Array? | List of subscribed event strings. null if no events are selected. |
maskedSecret | String? | Masked preview of the signing secret (e.g. "whsec_...a1b2c"). null if no secret has been generated yet. |
{
"statusCode": 200,
"message": "Success",
"data": {
"webhookUrl": "https://api.yourdomain.com/webhooks/towercrown",
"webhookEvents": [
"shipment.created",
"shipment.delivered",
"shipment.canceled",
"wallet.funded"
],
"maskedSecret": "whsec_...a1b2c"
}
}
Save Webhook Configuration
/v1/webhook/configRequired permission: webhook:get
Update the registered URL and/or subscribed events. The existing signing secret is preserved. this call does not rotate it.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | String | ❌ | Your HTTPS callback URL. Must start with https:// or http://. |
events | Array | ❌ | List of event strings to subscribe to. See Event Catalog for valid values. |
Both fields are optional individually, but you should pass at least one. Omitting url keeps the existing URL; omitting events clears the subscriptions.
{
"url": "https://api.yourdomain.com/webhooks/towercrown",
"events": [
"shipment.created",
"shipment.delivered",
"shipment.canceled",
"wallet.funded"
]
}
Generate / Rotate Signing Secret
/v1/webhook/config/secretRequired permission: webhook:secret:update
Generates a new HMAC signing secret. The full secret is returned exactly once in the response. copy it immediately and store it securely. Future calls to GET /v1/webhook/config will only show the masked version.
Rotating the secret invalidates the previous one. Any server still verifying with the old secret will start rejecting deliveries until updated.
Response
| Field | Type | Description |
|---|---|---|
webhookUrl | String? | Current registered URL. |
webhookEvents | Array? | Current subscribed events. |
secret | String | The full plaintext signing secret. only returned here, once. Starts with whsec_. |
{
"statusCode": 200,
"message": "Webhook secret generated successfully",
"data": {
"webhookUrl": "https://api.yourdomain.com/webhooks/towercrown",
"webhookEvents": [
"shipment.created",
"shipment.delivered"
],
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
}
}
Delivery Logs
/v1/webhook/logsRequired permission: webhook:log:get
Returns the history of webhook delivery attempts for the current workspace and environment.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | Integer | ❌ | Max records per page. Defaults to 20. |
cursor | String | ❌ | Pagination cursor from a previous response. |
startDate | String | ❌ | ISO 8601 filter start date. |
endDate | String | ❌ | ISO 8601 filter end date. |
Log Item Fields
| Field | Type | Description |
|---|---|---|
id | String | Unique delivery log ID (e.g. WHL_A1B2C3D4). |
parentId | String? | ID of the original log if this entry is a replay. null for original deliveries. |
timestamp | String | ISO 8601 timestamp of the delivery attempt. |
event | String | The event type that triggered this delivery. |
url | String | The endpoint URL that was called. |
statusCode | Integer | HTTP status code returned by your server. 504 indicates a timeout or connection failure. |
payload | String | The JSON string that was sent as the request body. |
response | String | The raw response body returned by your server. |
latencyMs | Integer | Round-trip time in milliseconds. |
attempts | Integer | Number of times this payload has been delivered (including replays). |
{
"statusCode": 200,
"message": "Success",
"data": {
"items": [
{
"id": "WHL_A1B2C3D4E5",
"parentId": null,
"timestamp": "2026-07-01T17:42:05Z",
"event": "shipment.created",
"url": "https://api.yourdomain.com/webhooks/towercrown",
"statusCode": 200,
"payload": "{"id":"SHP_Z8F9A2B3C4","trackingCode":"TCL-SB-3891829"}",
"response": "ok",
"latencyMs": 148,
"attempts": 1
}
],
"nextCursor": null
}
}
Replay a Delivery
/v1/webhook/:id/replayRequired permission: webhook:log:replay
Re-dispatches a previously logged webhook delivery using the same payload. A new log entry is created linked to the original via parentId. The X-Towercrown-Replay: true header is added to the outgoing request so your server can distinguish replays.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | String | ✅ | The log ID to replay (e.g. WHL_A1B2C3D4E5). |
{
"statusCode": 200,
"message": "Webhook replayed successfully",
"data": {
"id": "WHL_F6G7H8I9J0",
"parentId": "WHL_A1B2C3D4E5",
"timestamp": "2026-07-01T18:30:00Z",
"event": "shipment.created",
"url": "https://api.yourdomain.com/webhooks/towercrown",
"statusCode": 200,
"payload": "{"id":"SHP_Z8F9A2B3C4","trackingCode":"TCL-SB-3891829"}",
"response": "ok",
"latencyMs": 102,
"attempts": 2
}
}