Webhooks del Merchant
Gestiona los endpoints de webhook de un Merchant desde el Dashboard: crea configuraciones, inspecciona entregas y rota los secretos de firma.
Estos endpoints respaldan la pantalla de webhooks del Dashboard. Una configuración de webhook es una URL a la que Tokeflow entrega eventos firmados, además del filtro de eventos y el secreto de firma que la rigen. Desde aquí registras endpoints, observas entregas y sus reintentos, y rotas el secreto de firma whsec_….
El secreto de firma se muestra únicamente cuando se crea o se rota — guárdalo de inmediato. Cada entrega está firmada; el endpoint receptor debe verificar la firma antes de actuar. Consulta Verificar firmas.
Estos endpoints impulsan la interfaz del Tokeflow Dashboard. Están autenticados por sesión (JWT bearer) — el token proviene de iniciar sesión en el Dashboard, no de una clave de API sk_/pk_. Las solicitudes también incluyen el header x-merchant-id, que identifica al Merchant en contexto, y el usuario que inició sesión debe ser miembro con acceso a él.
Endpoints
GET/api/v1/merchant/webhooks
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Lista las configuraciones de webhook.
Parámetros de consulta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
page | number | No | Número de página (indexado desde 1). Predeterminado 1, mín. 1. |
limit | number | No | Número de elementos por página. Predeterminado 20, mín. 1, máx. 100. |
Ejemplo de solicitud
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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Crea una configuración de webhook.
Campos de la solicitud
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
url | string | Sí | La URL a donde se enviarán los eventos de webhook. |
description | string | No | Descripción opcional para esta configuración de webhook. |
event_filter | array | No | Lista de tipos de evento a los que suscribirse. Si no se proporciona, se enviarán todos los eventos. |
Ejemplo de solicitud
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"
]
}'Ejemplo de respuesta — 201
{
"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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Lista todas las entregas de webhook.
Parámetros de consulta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
page | number | No | Número de página (indexado desde 1). Predeterminado 1, mín. 1. |
limit | number | No | Número de elementos por página. Predeterminado 20, mín. 1, máx. 100. |
status | string | No | Filtra por estado de entrega |
from | string | No | Timestamp de inicio (formato ISO 8601) - filtra entregas posteriores a este momento |
to | string | No | Timestamp de fin (formato ISO 8601) - filtra entregas anteriores a este momento |
Ejemplo de solicitud
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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Elimina una configuración de webhook.
Parámetros de ruta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | Sí | — |
Ejemplo de solicitud
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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Obtiene una configuración de webhook por ID.
Parámetros de ruta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | Sí | — |
Ejemplo de solicitud
curl https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "x-merchant-id: mrc_8a3f12d9"Ejemplo de respuesta — 200
{
"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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Actualiza una configuración de webhook.
Parámetros de ruta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | Sí | — |
Campos de la solicitud
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
url | string | No | La URL a donde se enviarán los eventos de webhook. |
description | string | No | Descripción opcional para esta configuración de webhook. |
event_filter | array | No | Lista de tipos de evento a los que suscribirse. |
is_active | boolean | No | Si esta configuración de webhook está activa. |
Ejemplo de solicitud
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
}'Ejemplo de respuesta — 200
{
"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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Lista las entregas de un webhook.
Parámetros de ruta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | Sí | — |
Parámetros de consulta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
page | number | No | Número de página (indexado desde 1). Predeterminado 1, mín. 1. |
limit | number | No | Número de elementos por página. Predeterminado 20, mín. 1, máx. 100. |
status | string | No | Filtra por estado de entrega |
from | string | No | Timestamp de inicio (formato ISO 8601) - filtra entregas posteriores a este momento |
to | string | No | Timestamp de fin (formato ISO 8601) - filtra entregas anteriores a este momento |
Ejemplo de solicitud
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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Reenvía una entrega de webhook específica.
Parámetros de ruta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | Sí | — |
deliveryId | string | Sí | — |
Ejemplo de solicitud
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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Rota el secreto de firma del webhook.
Parámetros de ruta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | Sí | — |
Ejemplo de solicitud
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"Ejemplo de respuesta — 201
{
"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
Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.
Envía un evento de prueba a un endpoint de webhook.
Parámetros de ruta
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string | Sí | — |
Ejemplo de solicitud
curl -X POST https://api.tokeflow.com/api/v1/merchant/webhooks/obj_1a2b3c4d/test \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "x-merchant-id: mrc_8a3f12d9"Errores
Los errores usan el envoltorio estándar. Los casos más comunes aquí:
| HTTP | Significado |
|---|---|
400 | Parámetros inválidos o un estado que no permite esta operación. |
401 | Token de sesión del Dashboard ausente, expirado o inválido. |
403 | Autenticado, pero el usuario que inició sesión no tiene acceso a esta entidad. |
404 | El registro no existe o no es visible para esta entidad. |