Registrar Webhook
Endpoints para crear, listar y remover webhooks de notificacion.
Crear Webhook
POST /api/external/webhooksHeaders
| Header | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
Authorization | String | Si | ApiKey {client_id}:{client_secret} |
Content-Type | String | Si | application/json |
hmac | String | Si | Firma HMAC-SHA512 del body (mas informacion) |
Request Body
| Campo | Tipo | Obligatorio | Default | Descripcion |
|---|---|---|---|---|
url | String | Si | -- | URL para recibir notificaciones (HTTPS por defecto) |
events | Array | Si | -- | Lista de eventos a suscribir. Debe ser un array no-vacio con al menos un evento valido de la tabla abajo. Omitir el campo retorna 400 {"errors": {"events": ["can't be blank"]}}. |
secret | String | No | auto-generado | Clave para firma HMAC-SHA256 de las entregas. Si se omite, un valor aleatorio es generado automaticamente. |
description | String | No | null | Descripcion libre del webhook para identificacion interna |
allow_insecure | Boolean | No | false | Permite URLs HTTP (no-HTTPS). La seguridad de los datos es responsabilidad del cliente. |
Eventos disponibles (PIX, TEF entre cuentas Minha Konta y prueba operacional de webhook):
| Evento | Status body | Descripcion | Disparo |
|---|---|---|---|
pix.charge.created | created | QR code generado o cash-in iniciado | Activo |
pix.charge.paid | paid | PIX recibido y liquidado | Activo |
pix.charge.expired | expired | QR code expiro sin pago | Activo |
pix.charge.cancelled | cancelled | QR code cancelado antes del pago | Registrado, aun no disparado |
pix.payout.queued | queued | PIX enviado encolado por limite operacional | Activo |
pix.payout.processing | processing | PIX enviado, aguardando confirmacion | Activo |
pix.payout.confirmed | settled | PIX enviado y confirmado (terminal) | Activo |
pix.payout.failed | rejected | PIX enviado rechazado (terminal) | Activo |
pix.payout.returned | returned | PIX enviado devuelto | Activo |
pix.refund.requested | requested | Solicitud de devolucion recibida (infraccion BACEN); bloqueo cautelar creado en el saldo del cliente | Activo |
pix.refund.completed | settled / completed | Analisis de la defensa finalizado y devolucion ejecutada (o liberada) | Activo |
pix.return.received | settled | Devolucion PIX recibida (credito) | Activo |
pix.infraction.created | ACKNOWLEDGED | Infraccion PIX reportada por la contraparte via BACEN DICT | Activo |
pix.infraction.resolved | CLOSED / CANCELLED | Infraccion resuelta por decision final o cancelacion de la contraparte | Activo |
pix.infraction.defense_submitted | defense_submitted | Defensa enviada por el merchant | Activo |
tef.transfer.sent | settled | TEF entre cuentas Minha Konta liquidada para la cuenta de origen | Activo |
tef.transfer.received | settled | TEF entre cuentas Minha Konta liquidada para la cuenta de destino | Activo |
tef.transfer.failed | failed | TEF entre cuentas Minha Konta rechazada o no liquidada | Activo |
webhook.test | test | Prueba manual. Disponible solo via portal Admin/Merchant - no hay endpoint External API para disparar | Disparo manual |
pix.charge.cancelled aun no es disparado
El evento puede ser suscrito, pero todavia no hay flujo publico de cancelacion de QR code que dispare este tipo de notificacion. Puede incluirlo en el array events - la API acepta - pero ninguna notificacion llegara a su endpoint hasta que el flujo sea disponibilizado.
Cualquier evento fuera de esa tabla es rechazado
Al crear un webhook, cada evento solicitado se valida contra la lista publica de eventos soportados. Eventos desconocidos (boleto.paid, account.created, sta.file.*, etc.) retornan 400 con error events: contains invalid events: ....
Payloads de cada evento
Ejemplos de payload completos para cada evento estan en Payloads de los Webhooks.
Ejemplo
BODY='{"url":"https://seusite.com.br/webhook","events":["pix.charge.paid","pix.payout.confirmed"]}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')
curl -X POST https://api.minhakonta.com/api/external/webhooks \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "hmac: $HMAC" \
-d "$BODY"Respuesta de Exito (201)
{
"worked": true,
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"url": "https://seusite.com.br/webhook",
"events": ["pix.charge.paid", "pix.payout.confirmed"],
"secret": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"description": null,
"is_active": true,
"created_at": "2026-03-07T15:30:00Z"
}Formato del id
El id del webhook es un UUID v4 canonico (36 caracteres con guiones). Use ese valor directo en DELETE /api/external/webhooks/:id.
Respuesta de Error (422)
{
"worked": false,
"detail": "URL deve utilizar HTTPS"
}Solo HTTPS por Default
La URL del webhook debe usar HTTPS. URLs con HTTP seran rechazadas, a menos que allow_insecure: true sea enviado en el registro.
Importante - Secret del Webhook
El campo secret retornado en la respuesta del registro es la clave usada para firmar las entregas del webhook (HMAC-SHA256). Almacene ese valor con seguridad tan pronto lo reciba - es el que valida que una notificacion vino realmente de Minha Konta.
NO confunda con client_secret:
client_secret= autenticacion de sus solicitudes a la API (header Authorization)secretdel webhook = verificacion de la firma de las entregas recibidas (header X-Minha Konta-Signature)
Si usted no envia el campo secret en el registro, un valor aleatorio sera generado automaticamente y retornado en la respuesta.
Vea Validacion de Webhooks para ejemplos de como verificar la firma.
Recuperando el secret despues
El secret es retornado tanto en POST /api/external/webhooks (creacion) como en GET /api/external/webhooks y GET /api/external/webhooks/:id (consulta). Si usted perdio el valor, basta consultar el webhook nuevamente via GET.
En una futura version este comportamiento puede ser restringido (exhibir solo en la creacion); recomendamos almacenar el secret en un secreto gestionado (vault, SSM, etc.) en el momento del registro.
URLs HTTP
Por defecto, los webhooks exigen HTTPS para garantizar la seguridad de los datos en transito. Para utilizar HTTP, envie allow_insecure: true en el registro del webhook.
Atencion
URLs HTTP transmiten datos sin cifrado. La seguridad y el secreto de las informaciones transitadas quedan bajo entera responsabilidad del cliente. Minha Konta realiza la entrega del webhook normalmente, pero no se responsabiliza por interceptacion o fuga de datos en conexiones no cifradas.
URLs privadas son siempre bloqueadas
Incluso con allow_insecure: true, URLs apuntando para direcciones privadas/internas son rechazadas:
localhost/127.x.x.x- RFC1918:
10.x.x.x,192.168.x.x,172.16-31.x.x - TLDs internos:
.local,.internal
Webhooks deben apuntar para URLs publicas accesibles por internet.
Listar Webhooks
GET /api/external/webhooksHeaders
| Header | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
Authorization | String | Si | ApiKey {client_id}:{client_secret} |
Ejemplo
curl -X GET https://api.minhakonta.com/api/external/webhooks \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"Respuesta de Exito (200)
Retorna un array de objetos (no envuelto en {"worked": true}). Cada item contiene los mismos campos del registro, incluyendo secret.
[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"url": "https://seusite.com.br/webhook",
"events": ["pix.charge.paid", "pix.payout.confirmed"],
"description": null,
"account_id": 10014,
"is_active": true,
"allow_insecure": false,
"status": "active",
"secret": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"created_at": "2026-03-07T15:30:00",
"updated_at": "2026-03-07T15:30:00"
}
]| Campo | Tipo | Descripcion |
|---|---|---|
id | string (UUID) | Identificador del webhook |
url | string | URL de destino |
events | array | Eventos suscritos |
description | string o null | Descripcion opcional |
account_id | integer o null | Cuenta asociada. null = webhook global para la API key (si soportado) |
is_active | boolean | false = webhook pausado, ninguna delivery es disparada |
allow_insecure | boolean | true = URLs HTTP aceptadas |
status | string | Derivado de is_active - "active" o "inactive" |
secret | string | Clave HMAC-SHA256 usada para firmar entregas. Retornada en el LIST para permitir recuperacion caso el cliente haya perdido el valor original |
created_at / updated_at | string ISO 8601 | Timestamps en UTC, formato NaiveDateTime (sin sufijo Z, ej: "2026-03-07T15:30:00"). Diferente de otros campos de fecha en payloads de webhook (paid_at, returned_at, expired_at) que usan DateTime ISO 8601 con Z final. Siempre asuma UTC para los campos del webhook object |
Remover Webhook
DELETE /api/external/webhooks/:idHeaders
| Header | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
Authorization | String | Si | ApiKey {client_id}:{client_secret} |
Path Parameters
| Parametro | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
id | String (UUID) | Si | ID del webhook (UUID v4 retornado por el endpoint de creacion) |
Ejemplo
curl -X DELETE https://api.minhakonta.com/api/external/webhooks/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"Respuesta de Exito (204)
HTTP 204 No Content - body vacio. El webhook fue removido con exito; ninguna delivery pendiente sera disparada.
Primera llamada: 204. Subsecuentes: 404
La primera llamada exitosa retorna 204 No Content. Llamadas subsecuentes con el mismo id retornan 404 { "errors": { "not_found": "webhook not found" } } - el webhook ya fue removido. Esto no es idempotencia estricta HTTP (en que toda llamada retornaria 204) - es el comportamiento estandar de DELETE cuando el recurso deja de existir. Escriba su integracion para aceptar tanto 204 como 404 como "el webhook no esta mas activo".
Respuesta de Error (400)
Formato de id invalido (no es UUID):
{
"errors": {
"bad_request": "id must be a valid UUID"
}
}Respuesta de Error (404)
Webhook no existe o no pertenece a su cuenta:
{
"errors": {
"not_found": "webhook not found"
}
}