Skip to main content
The Webhooks API allows you to manage webhook endpoints that receive real-time event notifications when activities occur in your account.

List webhook endpoints

GET /v1/webhook_endpoints
Returns a paginated list of webhook endpoints for the current account.
page
integer
default:"1"
Page number for pagination.
curl https://api.gettrxn.com/v1/webhook_endpoints \
  -H "Authorization: Bearer $TRXN_TOKEN"
Response
{
  "webhook_endpoints": [
    {
      "id": "we_xxx",
      "url": "https://example.com/webhook",
      "description": "Production webhook",
      "enabled": true,
      "subscriptions": ["*"],
      "created_at": "2025-01-14T12:00:00Z",
      "updated_at": "2025-01-14T12:00:00Z",
      "signing_secret_last4": "a1b2"
    }
  ],
  "pagination": {
    "page": 1,
    "pages": 1,
    "count": 1
  }
}

Get webhook endpoint

GET /v1/webhook_endpoints/:id
Returns details of a specific webhook endpoint.
id
string
required
The webhook endpoint’s ID (e.g., we_xxx).
curl https://api.gettrxn.com/v1/webhook_endpoints/we_xxx \
  -H "Authorization: Bearer $TRXN_TOKEN"
Response
{
  "id": "we_xxx",
  "url": "https://example.com/webhook",
  "description": "Production webhook",
  "enabled": true,
  "subscriptions": ["invoice.created", "invoice.paid"],
  "created_at": "2025-01-14T12:00:00Z",
  "updated_at": "2025-01-14T12:00:00Z",
  "signing_secret_last4": "a1b2"
}

Create webhook endpoint

POST /v1/webhook_endpoints
Creates a new webhook endpoint.
url
string
required
The URL where webhook events will be sent via HTTP POST. Must use HTTPS.
subscriptions
array
required
Event types to subscribe to. Use ["*"] for all events, or specify individual events like ["invoice.created", "invoice.paid"].
enabled
boolean
default:"true"
Whether the endpoint is active.
description
string
Optional description for the endpoint.
curl -X POST https://api.gettrxn.com/v1/webhook_endpoints \
  -H "Authorization: Bearer $TRXN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhook",
    "subscriptions": ["invoice.created", "invoice.paid"],
    "enabled": true,
    "description": "Invoice notifications"
  }'
The signing secret is only returned in full once — at creation time. Store it securely as you will need it to verify webhook signatures.
The response includes the full signing_secret (returned as 201 Created).

Update webhook endpoint

PUT /v1/webhook_endpoints/:id
Updates an existing webhook endpoint.
id
string
required
The webhook endpoint’s ID.
url
string
The endpoint URL.
subscriptions
array
Event types to subscribe to.
enabled
boolean
Whether the endpoint is active.
description
string
Optional description.
curl -X PUT https://api.gettrxn.com/v1/webhook_endpoints/we_xxx \
  -H "Authorization: Bearer $TRXN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": false
  }'
Returns the updated webhook endpoint.

Delete webhook endpoint

DELETE /v1/webhook_endpoints/:id
Deletes a webhook endpoint. This also deletes all associated webhook events.
id
string
required
The webhook endpoint’s ID.
curl -X DELETE https://api.gettrxn.com/v1/webhook_endpoints/we_xxx \
  -H "Authorization: Bearer $TRXN_TOKEN"
Returns 204 No Content.

Regenerate signing secret

POST /v1/webhook_endpoints/:id/regenerate_secret
Regenerates the signing secret for a webhook endpoint. The previous secret is immediately invalidated.
id
string
required
The webhook endpoint’s ID.
curl -X POST https://api.gettrxn.com/v1/webhook_endpoints/we_xxx/regenerate_secret \
  -H "Authorization: Bearer $TRXN_TOKEN"
Returns the webhook endpoint with the new full signing_secret.
After regenerating the secret, you must update your integration to use the new secret. Webhooks signed with the old secret will fail verification.

Webhook security

TRXN signs all webhook requests with HMAC-SHA256 signatures, allowing you to verify that webhooks are genuinely from TRXN.

Signature header format

Every webhook request includes an X-Trxn-Signature header:
X-Trxn-Signature: t=<unix_timestamp>,v1=<signature>
Example:
X-Trxn-Signature: t=1704067200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Signing secret format

Signing secrets use the format whsec_<64_hex_chars>:
whsec_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2

Verifying signatures

To verify a webhook signature:
  1. Extract the timestamp (t) and signature (v1) from the header.
  2. Check the timestamp is within 5 minutes of current time (prevents replay attacks).
  3. Compute the expected signature: HMAC-SHA256(secret, "<timestamp>.<raw_body>").
  4. Compare signatures using constant-time comparison.
Use the full signing secret (including the whsec_ prefix) as the HMAC key. This matches Stripe’s implementation.
def verify_webhook(payload, signature_header, secret)
  parts = signature_header.split(",").to_h { |p| p.split("=", 2) }
  timestamp = parts["t"].to_i
  signature = parts["v1"]

  # Check timestamp is within 5 minutes
  return false if (Time.now.to_i - timestamp).abs > 300

  # Compute expected signature (use full secret including whsec_ prefix)
  signed_payload = "#{timestamp}.#{payload}"
  expected = OpenSSL::HMAC.hexdigest("SHA256", secret, signed_payload)

  # Constant-time comparison
  ActiveSupport::SecurityUtils.secure_compare(expected, signature)
end

Available events

EventDescription
customer.createdA new customer has been created.
customer.updatedA customer has been updated.
customer.deletedA customer has been deleted.
EventDescription
product.createdA new product has been created.
product.updatedA product has been updated.
product.deletedA product has been deleted.
EventDescription
price.createdA new price has been created.
price.updatedA price has been updated.
price.deletedA price has been deleted.
EventDescription
invoice.createdA new invoice has been created.
invoice.updatedAn invoice has been updated.
invoice.paidAn invoice has been marked as paid.
invoice.overdueAn invoice has become overdue.
EventDescription
subscription.createdA new subscription has been created.
subscription.activatedA subscription has become active.
subscription.canceledA subscription has been canceled.
subscription.renewedA subscription has been renewed.
EventDescription
subscription_phase.createdA new subscription phase has been created.
subscription_phase.updatedA subscription phase has been updated.
subscription_phase.deletedA subscription phase has been deleted.
EventDescription
wallet.createdA new wallet has been created.
EventDescription
crypto_address.createdA new crypto address has been added to a wallet.
crypto_address.deletedA crypto address has been deleted.
EventDescription
payment_claim.submittedA customer has submitted a payment claim.
payment_claim.approvedA payment claim has been approved.
payment_claim.rejectedA payment claim has been rejected.
EventDescription
crypto_transaction.receivedA crypto transaction has been received.
crypto_transaction.allocatedA transaction has been allocated to an invoice.
EventDescription
transaction_allocation.createdA new transaction allocation has been created.

Webhook payload format

When an event occurs, TRXN sends a POST request to your endpoint with the following format:
{
  "event": "invoice.created",
  "payload": {
    "id": "inv_xxx",
    "object": "invoice",
    "customer_id": "cus_xxx",
    "status": "pending",
    "total_amount": "100.00"
  },
  "timestamp": "2025-01-14T12:00:00Z"
}

Subscription phase payload example

{
  "event": "subscription_phase.created",
  "payload": {
    "id": "sub_phase_xxx",
    "object": "subscription_phase",
    "subscription_id": "sub_xxx",
    "start_date": "2025-02-01T00:00:00Z",
    "end_date": "2025-03-01T00:00:00Z",
    "items": [
      {
        "id": 123,
        "price_id": "price_xxx",
        "quantity": 1,
        "overridden_price_amount": null
      }
    ],
    "created_at": "2025-01-26T12:00:00Z",
    "updated_at": "2025-01-26T12:00:00Z"
  },
  "timestamp": "2025-01-26T12:00:00Z"
}

Response handling

Your endpoint should respond with a 2xx status code to indicate successful receipt. If your endpoint returns a non-2xx status code, TRXN will retry the delivery with exponential backoff (up to 11 attempts).

Error handling

If your endpoint cannot be reached, TRXN will:
  1. Connection error: Disable the endpoint to prevent further delivery attempts.
  2. Timeout error: Retry with exponential backoff.
  3. TLS error: Retry with exponential backoff.
  4. Non-2xx response: Retry with exponential backoff.

Event retention

TRXN retains webhook events for 30 days.

Best practices

Return a 2xx response before any complex logic to avoid timeouts. Process the event asynchronously after responding.
  1. Respond quickly: Return a 2xx response before any complex logic that could cause a timeout. Process the event asynchronously after responding.
  2. Handle duplicates: Webhook endpoints may occasionally receive the same event more than once. Make your event processing idempotent by tracking the id from the payload. If you have already processed an event for that resource, skip it and return a 2xx response.
  3. Handle out-of-order delivery: Events may not arrive in chronological order. Use the timestamp field to determine the sequence of events rather than assuming arrival order.
  4. Always verify signatures: Use the X-Trxn-Signature header to verify all incoming webhooks. Reject any webhook that fails signature verification.
  5. Use HTTPS: Always use HTTPS endpoints for security.
  6. Store secrets securely: Store your signing secrets in environment variables or a secrets manager, never in source code.
  7. Monitor failures: Check webhook events in the dashboard to monitor delivery status.
  8. Regenerate compromised secrets: If you suspect your signing secret has been compromised, regenerate it immediately.