Merchant webhooks

Manage a merchant's webhook endpoints from the Dashboard — create configs, inspect deliveries, and rotate signing secrets.

These endpoints back the Dashboard's webhooks screen. A webhook config is a URL Tokeflow delivers signed events to, plus the event filter and signing secret that govern it. From here you register endpoints, watch deliveries and their retries, and rotate the whsec_… secret.

The signing secret is shown only when created or rotated — store it immediately. Every delivery is signed; the receiving endpoint must verify the signature before acting. See Verifying signatures.

These endpoints power the Tokeflow Dashboard UI. They are session-authenticated (JWT bearer) — the token comes from signing in to the Dashboard, not from an sk_/pk_ API key. Requests also carry the x-merchant-id header identifying the merchant in context, and the signed-in user must be a member with access to it.


Endpoints

GET/api/v1/merchant/webhooks

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

List webhook configs.

Query parameters

FieldTypeRequiredDescription
pagenumberNoPage number (1-indexed). Default 1, min 1.
limitnumberNoNumber of items per page. Default 20, min 1, max 100.

Example request

curl -G https://api.tokeflow.com/api/v1/merchant/webhooks \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9" \
  --data-urlencode "page=1" \
  --data-urlencode "limit=20"

POST/api/v1/merchant/webhooks

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

Create webhook config.

Request fields

FieldTypeRequiredDescription
urlstringYesThe URL where webhook events will be sent.
descriptionstringNoOptional description for this webhook configuration.
event_filterarrayNoList of event types to subscribe to. If not provided, all events will be sent.

Example request

curl -X POST https://api.tokeflow.com/api/v1/merchant/webhooks \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/webhooks/payments",
    "description": "Production payment notifications",
    "event_filter": [
      "transaction.authorized",
      "transaction.failed",
      "transaction.refunded"
    ]
  }'

Example response201

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "merchant_id": "550e8400-e29b-41d4-a716-446655440001",
  "url": "https://api.example.com/webhooks/payments",
  "description": "Production payment notifications",
  "event_filter": [
    "transaction.authorized",
    "transaction.failed",
    "transaction.refunded"
  ],
  "is_active": true,
  "created_at": "2024-01-15T10:30:00.000Z",
  "updated_at": "2024-01-15T10:30:00.000Z",
  "last_triggered_at": "2024-01-15T10:30:00.000Z",
  "secret": "whsec_abc123def456..."
}

GET/api/v1/merchant/webhooks/deliveries

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

List all webhook deliveries.

Query parameters

FieldTypeRequiredDescription
pagenumberNoPage number (1-indexed). Default 1, min 1.
limitnumberNoNumber of items per page. Default 20, min 1, max 100.
statusstringNoFilter by delivery status
fromstringNoFrom timestamp (ISO 8601 format) - filter deliveries after this time
tostringNoTo timestamp (ISO 8601 format) - filter deliveries before this time

Example request

curl -G https://api.tokeflow.com/api/v1/merchant/webhooks/deliveries \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9" \
  --data-urlencode "page=1" \
  --data-urlencode "limit=20" \
  --data-urlencode "status=failed" \
  --data-urlencode "from=2024-01-01T00:00:00Z"

DELETE/api/v1/merchant/webhooks/:id

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

Delete webhook config.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl -X DELETE https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9"

GET/api/v1/merchant/webhooks/:id

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

Get webhook config by ID.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9"

Example response200

{
  "id": "obj_1a2b3c4d",
  "merchant_id": "mrc_8a3f12d9",
  "merchant": {
    "id": "obj_1a2b3c4d",
    "organization_id": "org_4b21e7c3",
    "organization": {
      "id": "obj_1a2b3c4d",
      "name": "Acme Store",
      "slug": "acme-store",
      "status": "active",
      "business_registration_number": "string",
      "mcc": "string",
      "country_code": "BR",
      "external_reference": "string",
      "phone_number": "+5511987654321",
      "address_line1": "string",
      "address_line2": "string",
      "city": "string",
      "state": "string",
      "postal_code": "string",
      "created_at": "2026-01-15T12:30:00.000Z",
      "updated_at": "2026-01-15T12:30:00.000Z",
      "memberships": [
        {
          "id": "obj_1a2b3c4d",
          "organization_id": "org_4b21e7c3",
          "user_id": "string",
          "role": "owner",
          "created_at": "2026-01-15T12:30:00.000Z",
          "updated_at": "2026-01-15T12:30:00.000Z",
          "organization": {},
          "user": {}
        }
      ],
      "merchants": [
        {}
      ],
      "branding": {
        "id": "obj_1a2b3c4d",
        "organization_id": "org_4b21e7c3",
        "organization": {},
        "custom_url": "https://example.com/webhooks/tokeflow",
        "site_title": "string",
        "favicon": "string",
        "logo_light_mode": "string",
        "logo_dark_mode": "string",
        "collapsible_logo_light_mode": "string",
        "collapsible_logo_dark_mode": "string",
        "theme_primary_color": "#1c1c1c",
        "theme_secondary_color": "#1c1c1c",
        "show_name_with_logo": true,
        "created_at": "2026-01-15T12:30:00.000Z",
        "updated_at": "2026-01-15T12:30:00.000Z"
      }
    },
    "name": "Acme Store",
    "slug": "acme-store",
    "external_reference": "string",
    "business_registration_number": "string",
    "mcc": "string",
    "phone_number": "+5511987654321",
    "address_line1": "string",
    "address_line2": "string",
    "city": "string",
    "state": "string",
    "postal_code": "string",
    "country_code": "BR",
    "website": "string",
    "status": "active",
    "created_at": "2026-01-15T12:30:00.000Z",
    "updated_at": "2026-01-15T12:30:00.000Z",
    "webhook_configs": [
      {}
    ],
    "memberships": [
      {
        "id": "obj_1a2b3c4d",
        "merchant_id": "mrc_8a3f12d9",
        "user_id": "string",
        "role": "owner",
        "created_at": "2026-01-15T12:30:00.000Z",
        "updated_at": "2026-01-15T12:30:00.000Z",
        "merchant": {},
        "user": {
          "id": "obj_1a2b3c4d",
          "organization_id": "org_4b21e7c3",
          "email": "jane@example.com",
          "name": "Acme Store",
          "auth_provider": "string",
          "auth_subject_id": "string",
          "password_hash": "string",
          "invitation_token": "string",
          "invitation_expires_at": "2026-01-15T12:30:00.000Z",
          "is_active": true,
          "last_login_at": "2026-01-15T12:30:00.000Z",
          "must_change_password": true,
          "refresh_token_hash": "string",
          "failed_login_attempts": 1,
          "locked_until": "2026-01-15T12:30:00.000Z",
          "created_at": "2026-01-15T12:30:00.000Z",
          "updated_at": "2026-01-15T12:30:00.000Z",
          "organization": {},
          "memberships": [
            {}
          ]
        }
      }
    ],
    "customers": [
      {
        "id": "obj_1a2b3c4d",
        "merchant_id": "mrc_8a3f12d9",
        "merchant": {},
        "email": "jane@example.com",
        "name": "Acme Store",
        "phone": "+5511987654321",
        "document_type": "12345678909",
        "document_number": "12345678909",
        "metadata": {},
        "billing_address": {},
        "created_at": "2026-01-15T12:30:00.000Z",
        "updated_at": "2026-01-15T12:30:00.000Z",
        "deleted_at": "2026-01-15T12:30:00.000Z"
      }
    ]
  },
  "url": "https://example.com/webhooks/tokeflow",
  "secret": {},
  "description": "Human-readable description",
  "event_filter": [
    "transaction.created"
  ],
  "is_active": true,
  "created_at": "2026-01-15T12:30:00.000Z",
  "updated_at": "2026-01-15T12:30:00.000Z",
  "deleted_at": "2026-01-15T12:30:00.000Z"
}

PATCH/api/v1/merchant/webhooks/:id

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

Update webhook config.

Path parameters

FieldTypeRequiredDescription
idstringYes

Request fields

FieldTypeRequiredDescription
urlstringNoThe URL where webhook events will be sent.
descriptionstringNoOptional description for this webhook configuration.
event_filterarrayNoList of event types to subscribe to.
is_activebooleanNoWhether this webhook configuration is active.

Example request

curl -X PATCH https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/webhooks/payments",
    "description": "Production payment notifications",
    "event_filter": [
      "transaction.authorized",
      "transaction.failed",
      "transaction.refunded"
    ],
    "is_active": true
  }'

Example response200

{
  "id": "obj_1a2b3c4d",
  "merchant_id": "mrc_8a3f12d9",
  "merchant": {
    "id": "obj_1a2b3c4d",
    "organization_id": "org_4b21e7c3",
    "organization": {
      "id": "obj_1a2b3c4d",
      "name": "Acme Store",
      "slug": "acme-store",
      "status": "active",
      "business_registration_number": "string",
      "mcc": "string",
      "country_code": "BR",
      "external_reference": "string",
      "phone_number": "+5511987654321",
      "address_line1": "string",
      "address_line2": "string",
      "city": "string",
      "state": "string",
      "postal_code": "string",
      "created_at": "2026-01-15T12:30:00.000Z",
      "updated_at": "2026-01-15T12:30:00.000Z",
      "memberships": [
        {
          "id": "obj_1a2b3c4d",
          "organization_id": "org_4b21e7c3",
          "user_id": "string",
          "role": "owner",
          "created_at": "2026-01-15T12:30:00.000Z",
          "updated_at": "2026-01-15T12:30:00.000Z",
          "organization": {},
          "user": {}
        }
      ],
      "merchants": [
        {}
      ],
      "branding": {
        "id": "obj_1a2b3c4d",
        "organization_id": "org_4b21e7c3",
        "organization": {},
        "custom_url": "https://example.com/webhooks/tokeflow",
        "site_title": "string",
        "favicon": "string",
        "logo_light_mode": "string",
        "logo_dark_mode": "string",
        "collapsible_logo_light_mode": "string",
        "collapsible_logo_dark_mode": "string",
        "theme_primary_color": "#1c1c1c",
        "theme_secondary_color": "#1c1c1c",
        "show_name_with_logo": true,
        "created_at": "2026-01-15T12:30:00.000Z",
        "updated_at": "2026-01-15T12:30:00.000Z"
      }
    },
    "name": "Acme Store",
    "slug": "acme-store",
    "external_reference": "string",
    "business_registration_number": "string",
    "mcc": "string",
    "phone_number": "+5511987654321",
    "address_line1": "string",
    "address_line2": "string",
    "city": "string",
    "state": "string",
    "postal_code": "string",
    "country_code": "BR",
    "website": "string",
    "status": "active",
    "created_at": "2026-01-15T12:30:00.000Z",
    "updated_at": "2026-01-15T12:30:00.000Z",
    "webhook_configs": [
      {}
    ],
    "memberships": [
      {
        "id": "obj_1a2b3c4d",
        "merchant_id": "mrc_8a3f12d9",
        "user_id": "string",
        "role": "owner",
        "created_at": "2026-01-15T12:30:00.000Z",
        "updated_at": "2026-01-15T12:30:00.000Z",
        "merchant": {},
        "user": {
          "id": "obj_1a2b3c4d",
          "organization_id": "org_4b21e7c3",
          "email": "jane@example.com",
          "name": "Acme Store",
          "auth_provider": "string",
          "auth_subject_id": "string",
          "password_hash": "string",
          "invitation_token": "string",
          "invitation_expires_at": "2026-01-15T12:30:00.000Z",
          "is_active": true,
          "last_login_at": "2026-01-15T12:30:00.000Z",
          "must_change_password": true,
          "refresh_token_hash": "string",
          "failed_login_attempts": 1,
          "locked_until": "2026-01-15T12:30:00.000Z",
          "created_at": "2026-01-15T12:30:00.000Z",
          "updated_at": "2026-01-15T12:30:00.000Z",
          "organization": {},
          "memberships": [
            {}
          ]
        }
      }
    ],
    "customers": [
      {
        "id": "obj_1a2b3c4d",
        "merchant_id": "mrc_8a3f12d9",
        "merchant": {},
        "email": "jane@example.com",
        "name": "Acme Store",
        "phone": "+5511987654321",
        "document_type": "12345678909",
        "document_number": "12345678909",
        "metadata": {},
        "billing_address": {},
        "created_at": "2026-01-15T12:30:00.000Z",
        "updated_at": "2026-01-15T12:30:00.000Z",
        "deleted_at": "2026-01-15T12:30:00.000Z"
      }
    ]
  },
  "url": "https://example.com/webhooks/tokeflow",
  "secret": {},
  "description": "Human-readable description",
  "event_filter": [
    "transaction.created"
  ],
  "is_active": true,
  "created_at": "2026-01-15T12:30:00.000Z",
  "updated_at": "2026-01-15T12:30:00.000Z",
  "deleted_at": "2026-01-15T12:30:00.000Z"
}

GET/api/v1/merchant/webhooks/:id/deliveries

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

List deliveries for webhook.

Path parameters

FieldTypeRequiredDescription
idstringYes

Query parameters

FieldTypeRequiredDescription
pagenumberNoPage number (1-indexed). Default 1, min 1.
limitnumberNoNumber of items per page. Default 20, min 1, max 100.
statusstringNoFilter by delivery status
fromstringNoFrom timestamp (ISO 8601 format) - filter deliveries after this time
tostringNoTo timestamp (ISO 8601 format) - filter deliveries before this time

Example request

curl -G https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d/deliveries \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9" \
  --data-urlencode "page=1" \
  --data-urlencode "limit=20" \
  --data-urlencode "status=failed" \
  --data-urlencode "from=2024-01-01T00:00:00Z"

POST/api/v1/merchant/webhooks/:id/deliveries/:deliveryId/resend

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

Resend a specific webhook delivery.

Path parameters

FieldTypeRequiredDescription
idstringYes
deliveryIdstringYes

Example request

curl -X POST https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d/deliveries/123/resend \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9"

POST/api/v1/merchant/webhooks/:id/rotate-secret

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

Rotate webhook signing secret.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl -X POST https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d/rotate-secret \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9"

Example response201

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "merchant_id": "550e8400-e29b-41d4-a716-446655440001",
  "url": "https://api.example.com/webhooks/payments",
  "description": "Production payment notifications",
  "event_filter": [
    "transaction.authorized",
    "transaction.failed",
    "transaction.refunded"
  ],
  "is_active": true,
  "created_at": "2024-01-15T10:30:00.000Z",
  "updated_at": "2024-01-15T10:30:00.000Z",
  "last_triggered_at": "2024-01-15T10:30:00.000Z",
  "secret": "whsec_abc123def456..."
}

POST/api/v1/merchant/webhooks/:id/test

Merchant

Auth: Dashboard session (JWT bearer). Merchant membership required.

Send a test event to a webhook endpoint.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl -X POST https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d/test \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
  -H "x-merchant-id: mrc_8a3f12d9"

Errors

Errors use the standard envelope. The most common cases here:

HTTPMeaning
400Invalid parameters or a state that does not allow this operation.
401Missing, expired, or invalid Dashboard session token.
403Authenticated, but the signed-in user lacks access to this entity.
404The record does not exist or is not visible to this entity.

On this page