Webhooks

Subscribe to real-time event notifications. Txtly will send an HTTPS POST to your endpoint whenever an event occurs.

Create a webhook

POST
/v1/webhooks

Register a new webhook endpoint.

Request body

ParameterTypeDescription
endpointUrlrequiredstringHTTPS URL to receive webhook deliveries.
eventsrequiredstring[]Event types to subscribe to. Valid values: email.sent, email.delivered, email.bounced, email.complained, email.opened, email.clicked, email.delivery_delayed.
cURL
curl -X POST https://api.txtly.com.au/v1/webhooks \
  -H "Authorization: Bearer tx_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "endpointUrl": "https://yourapp.com/webhooks/txtly",
    "events": ["email.delivered", "email.bounced", "email.complained"]
  }'
Response — 201 Created
{
  "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "endpointUrl": "https://yourapp.com/webhooks/txtly",
  "events": ["email.delivered", "email.bounced", "email.complained"],
  "signingSecret": "whsec_a1b2c3d4e5f6...",
  "status": "active",
  "createdAt": "2026-03-21T00:00:00Z"
}

List webhooks

GET
/v1/webhooks

List all webhooks for the current team.

Get a webhook

GET
/v1/webhooks/{id}

Retrieve a webhook by ID.

Update a webhook

PATCH
/v1/webhooks/{id}

Update the endpoint URL or subscribed events.

Delete a webhook

DELETE
/v1/webhooks/{id}

Remove a webhook subscription.

Rotate the signing secret

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

Generate a new signing secret for the webhook. Deliveries are signed with the new secret immediately.

Response — 200 OK
{
  "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "endpointUrl": "https://yourapp.com/webhooks/txtly",
  "events": ["email.delivered", "email.bounced"],
  "signingSecret": "whsec_NEW_SECRET...",
  "status": "active",
  "createdAt": "2026-03-21T00:00:00Z"
}

List deliveries

GET
/v1/webhooks/{id}/deliveries

List delivery attempts for a webhook with cursor-based pagination.

Query parameters

ParameterTypeDescription
limitnumberResults per page (default: 20, max: 100).
cursorstringCursor for pagination (from previous response).
statusstringFilter by delivery status: pending, delivered, failed.
eventTypestringFilter by event type (e.g. email.bounced).
Response — 200 OK
{
  "data": [
    {
      "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
      "webhookId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
      "eventType": "email.delivered",
      "status": "delivered",
      "attempts": 1,
      "responseStatusCode": 200,
      "lastAttemptAt": "2026-03-21T14:30:02Z",
      "nextRetryAt": null,
      "createdAt": "2026-03-21T14:30:00Z"
    }
  ],
  "cursor": "2026-03-21T14:30:00.0000000Z|a1b2c3d4-5e6f-7890-abcd-ef1234567890",
  "hasMore": true
}

Get a delivery

GET
/v1/webhooks/{id}/deliveries/{deliveryId}

Retrieve a single delivery including its full payload, endpoint URL, attempt count, and last response status code.

Replay a delivery

POST
/v1/webhooks/{id}/deliveries/{deliveryId}/replay

Re-deliver an event. Creates a new pending delivery with the same payload as the original and returns it with 201 Created. The webhook must be active.

Signature verification

Every delivery is sent with three headers: webhook-id (the delivery ID), webhook-timestamp (Unix seconds), and webhook-signature. The signature header has the form v1,<base64 signature> where the signature is an HMAC-SHA256 of {timestamp}.{rawBody} computed with your signing secret. See the Webhook Events guide for implementation details.

Retry schedule

If your endpoint returns a non-2xx status code or does not respond within 15 seconds, Txtly retries delivery with exponential backoff (roughly 5 seconds up to 10 hours between attempts), making at most 6 attempts in total. After the final attempt fails, the delivery is marked as failed — you can re-send it with the replay endpoint.