Empieza gratis

Referencia de la API

Webhooks

Suscribe endpoints para recibir eventos firmados con HMAC, valida la URL antes de suscribirte, pausa o borra una suscripción y rota el secreto cuando quieras.

  • 7 operaciones
  • URL basehttps://api.messages.ccxcompany.co
  • AutenticaciónBearer con tu clave de API

El texto técnico de abajo viene del contrato público, openapi.json, en el idioma en que se escribió el contrato.

List webhook subscriptions

GET/webhooks

Returns paginated list. Filters: status, event, limit, skip. The secretCipher field is the encrypted blob — never the plaintext secret.

Parámetros

CampoDóndeTipoDescripción
statusopcionalquerystringValores:activepausedfailingrevoked
eventopcionalquerystringValores:message.sentmessage.deliveredmessage.readmessage.failedmessage.receivedcampaign.completednumber.quality_changedtemplate.approvedtemplate.rejectedcontact.createdcontact.opted_outapikey.createdapikey.rotatedsms.deliveredsms.failedsms.undeliveredsms.receivedemail.deliveredemail.bouncedemail.complainedemail.openedemail.clickedrcs.deliveredrcs.readrcs.failedsms.clickedrcs.clickedwallet.low_balancewallet.depletedinstagram.message.receivedinstagram.message.sentinstagram.message.failed
limitopcionalqueryinteger
skipopcionalqueryinteger

Respuestas

  • 200Default Response

    Campos y ejemplo de la respuesta
    CampoTipoDescripción
    itemsobligatorioobject[]
    items[].idobligatoriostringBranded Webhook id (wbh_ prefix + 21 nano-id chars).
    items[].organizationIdobligatoriostringBranded Organization id (org_ prefix + 21 nano-id chars).
    items[].urlobligatoriostring · uri
    items[].secretCipherobligatoriostringPII_CRITICAL — encrypted webhook signing secret (JSON-serialized EncryptedBlob, AAD bound to org+webhook). Never returned in plaintext after creation.
    items[].secretVersionobligatoriointeger
    items[].headersopcionalobject[]
    items[].headers[].keyobligatoriostring
    items[].headers[].valueobligatoriostring
    items[].eventsobligatoriostring[]
    items[].statusobligatoriostringValores:activepausedfailingrevoked
    items[].descriptionopcionalstring
    items[].retryobligatorioobject
    items[].retry.maxAttemptsobligatoriointeger
    items[].retry.backoffSecondsobligatoriointeger
    items[].createdByIdopcionalstringBranded Account id (acc_ prefix + 21 nano-id chars).
    items[].consecutiveFailuresopcionalinteger
    items[].lastSuccessAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    items[].lastFailureAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    items[].createdAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    items[].updatedAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    totalobligatoriointeger
    JSON
    {  "items": [    {      "id": "wbh_uV2aLwzXMqNmKjHbPiRoT",      "organizationId": "org_pGgniw5L7CTDSZDwjDrQ2",      "url": "https://api.partner.test/ccx/webhook",      "secretCipher": "string",      "secretVersion": 1,      "headers": [        {          "key": "X-Api-Key",          "value": "sk_live_…"        }      ],      "events": [        "message.sent"      ],      "status": "active",      "description": "string",      "retry": {        "maxAttempts": 8,        "backoffSeconds": 60      },      "createdById": "acc_dEws32WQG1MgvOVa6wqXT",      "consecutiveFailures": 0,      "lastSuccessAt": "2026-04-07T17:30:00.000Z",      "lastFailureAt": "2026-04-07T17:30:00.000Z",      "createdAt": "2026-04-07T17:30:00.000Z",      "updatedAt": "2026-04-07T17:30:00.000Z"    }  ],  "total": 3}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

Las respuestas de error siguen el formato RFC 7807 (application/problem+json), con un código estable en el campo code. Ver los códigos de error

Ejemplo en curl

cURL
curl 'https://api.messages.ccxcompany.co/webhooks' \  -H "Authorization: Bearer $CCX_API_KEY"
Solo los campos obligatorios. Cambia los valores de ejemplo por los tuyos.

Subscribe a webhook endpoint

POST/webhooks

Creates a webhook subscription with a fresh HMAC signing secret. The secret is encrypted at rest by the PII guardian (AES-256-GCM, AAD bound to org+webhook id) and returned exactly once in the reveal.secret field of the response. Caller MUST store it — it cannot be retrieved later.

Signing convention (Step 19 worker will use this):

  • Algorithm: HMAC-SHA256(secret, "${unix_ts}.${rawBody}")
  • Header: X-CCX-Signature: t=<unix>,v1=<hex>
  • Headers: X-CCX-Webhook-Id, X-CCX-Event, X-CCX-Delivery-Id
  • Secret format: whsec_<base64url>

Cuerpo de la peticiónapplication/json

CampoTipoDescripción
urlobligatoriostring · uriHTTPS endpoint that will receive signed POST requests.
eventsobligatoriostring[]Subscribed events. Closed enum from WEBHOOK_EVENTS.
descriptionopcionalstring
headersopcionalobject[]Custom headers forwarded on every delivery + the ping. Values are encrypted at rest; reserved (X-CCX-*, Host, …) names are rejected.
headers[].keyobligatoriostring
headers[].valueobligatoriostring
retryopcionalobject
retry.maxAttemptsobligatoriointeger
retry.backoffSecondsobligatoriointeger
Ejemplo completo del cuerpo
JSON
{  "url": "https://api.partner.test/ccx/webhook",  "events": [    "message.delivered",    "message.failed"  ],  "description": "Production CRM sync",  "headers": [    {      "key": "X-Api-Key",      "value": "sk_live_…"    }  ],  "retry": {    "maxAttempts": 8,    "backoffSeconds": 60  }}

Respuestas

  • 201Default Response

    Campos y ejemplo de la respuesta
    CampoTipoDescripción
    webhookobligatorioobject
    webhook.idobligatoriostringBranded Webhook id (wbh_ prefix + 21 nano-id chars).
    webhook.organizationIdobligatoriostringBranded Organization id (org_ prefix + 21 nano-id chars).
    webhook.urlobligatoriostring · uri
    webhook.secretCipherobligatoriostringPII_CRITICAL — encrypted webhook signing secret (JSON-serialized EncryptedBlob, AAD bound to org+webhook). Never returned in plaintext after creation.
    webhook.secretVersionobligatoriointeger
    webhook.headersopcionalobject[]
    webhook.headers[].keyobligatoriostring
    webhook.headers[].valueobligatoriostring
    webhook.eventsobligatoriostring[]
    webhook.statusobligatoriostringValores:activepausedfailingrevoked
    webhook.descriptionopcionalstring
    webhook.retryobligatorioobject
    webhook.retry.maxAttemptsobligatoriointeger
    webhook.retry.backoffSecondsobligatoriointeger
    webhook.createdByIdopcionalstringBranded Account id (acc_ prefix + 21 nano-id chars).
    webhook.consecutiveFailuresopcionalinteger
    webhook.lastSuccessAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    webhook.lastFailureAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    webhook.createdAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    webhook.updatedAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    revealobligatorioobject
    reveal.idobligatoriostringBranded Webhook id (wbh_ prefix + 21 nano-id chars).
    reveal.secretobligatoriostringPlaintext signing secret. Returned once by POST /webhooks and POST /webhooks/:id/rotate-secret. Caller MUST store it — it cannot be retrieved later.
    reveal.secretVersionobligatoriointeger
    reveal.createdAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    JSON
    {  "webhook": {    "id": "wbh_uV2aLwzXMqNmKjHbPiRoT",    "organizationId": "org_pGgniw5L7CTDSZDwjDrQ2",    "url": "https://api.partner.test/ccx/webhook",    "secretCipher": "string",    "secretVersion": 1,    "headers": [      {        "key": "X-Api-Key",        "value": "sk_live_…"      }    ],    "events": [      "message.sent"    ],    "status": "active",    "description": "string",    "retry": {      "maxAttempts": 8,      "backoffSeconds": 60    },    "createdById": "acc_dEws32WQG1MgvOVa6wqXT",    "consecutiveFailures": 0,    "lastSuccessAt": "2026-04-07T17:30:00.000Z",    "lastFailureAt": "2026-04-07T17:30:00.000Z",    "createdAt": "2026-04-07T17:30:00.000Z",    "updatedAt": "2026-04-07T17:30:00.000Z"  },  "reveal": {    "id": "wbh_uV2aLwzXMqNmKjHbPiRoT",    "secret": "whsec_aB3xY9zQ1pTkLmNoPqRsTuVwXyZ123456",    "secretVersion": 1,    "createdAt": "2026-04-07T17:30:00.000Z"  }}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 422RFC 7807 problem details for VALIDATION_ERROR (422).

Las respuestas de error siguen el formato RFC 7807 (application/problem+json), con un código estable en el campo code. Ver los códigos de error

Ejemplo en curl

cURL
curl -X POST 'https://api.messages.ccxcompany.co/webhooks' \  -H "Authorization: Bearer $CCX_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "url": "https://api.partner.test/ccx/webhook",    "events": [      "message.delivered",      "message.failed"    ]  }'
Solo los campos obligatorios. Cambia los valores de ejemplo por los tuyos.

Validate an endpoint before subscribing

POST/webhooks/validate

Pre-create check for the dashboard's Validar button. Runs the same SSRF guardian the dispatcher uses, then fires a single signed webhook.ping POST (ephemeral secret) and reports reachability.

Always 200; the body's ok flag carries the verdict and reason/message describe a failure (invalid URL, non-HTTPS, SSRF-blocked, non-2xx, timeout, unreachable) so the modal can render it inline.

Cuerpo de la peticiónapplication/json

CampoTipoDescripción
urlobligatoriostringEndpoint to validate. Checked for HTTPS + SSRF + a live signed webhook.ping.
headersopcionalobject[]Custom headers to include on the ping (as they would be on delivery).
headers[].keyobligatoriostring
headers[].valueobligatoriostring
Ejemplo completo del cuerpo
JSON
{  "url": "https://api.partner.test/ccx/webhook",  "headers": [    {      "key": "X-Api-Key",      "value": "sk_live_…"    }  ]}

Respuestas

  • 200Result of the pre-create ping. ok:true ⇒ endpoint returned 2xx; ok:false carries a reason the modal renders inline.

    Campos y ejemplo de la respuesta
    CampoTipoDescripción
    okobligatorioboolean
    statusCodeopcionalinteger
    latencyMsopcionalinteger
    reasonopcionalstringValores:invalid_urlinsecure_schemessrf_blockednon_2xxtimeoutunreachable
    messageopcionalstring
    JSON
    {  "ok": true,  "statusCode": 200,  "latencyMs": 142,  "reason": "invalid_url",  "message": "string"}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 422RFC 7807 problem details for VALIDATION_ERROR (422).

Las respuestas de error siguen el formato RFC 7807 (application/problem+json), con un código estable en el campo code. Ver los códigos de error

Ejemplo en curl

cURL
curl -X POST 'https://api.messages.ccxcompany.co/webhooks/validate' \  -H "Authorization: Bearer $CCX_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "url": "https://api.partner.test/ccx/webhook"  }'
Solo los campos obligatorios. Cambia los valores de ejemplo por los tuyos.

Get a single webhook subscription

GET/webhooks/{id}

Returns the full record. Cross-tenant requests get 404 (Mongo Guardian filter).

Parámetros

CampoDóndeTipoDescripción
idobligatoriorutastringBranded Webhook id (wbh_ prefix + 21 nano-id chars).

Respuestas

  • 200Default Response

    Campos y ejemplo de la respuesta
    CampoTipoDescripción
    idobligatoriostringBranded Webhook id (wbh_ prefix + 21 nano-id chars).
    organizationIdobligatoriostringBranded Organization id (org_ prefix + 21 nano-id chars).
    urlobligatoriostring · uri
    secretCipherobligatoriostringPII_CRITICAL — encrypted webhook signing secret (JSON-serialized EncryptedBlob, AAD bound to org+webhook). Never returned in plaintext after creation.
    secretVersionobligatoriointeger
    headersopcionalobject[]
    headers[].keyobligatoriostring
    headers[].valueobligatoriostring
    eventsobligatoriostring[]
    statusobligatoriostringValores:activepausedfailingrevoked
    descriptionopcionalstring
    retryobligatorioobject
    retry.maxAttemptsobligatoriointeger
    retry.backoffSecondsobligatoriointeger
    createdByIdopcionalstringBranded Account id (acc_ prefix + 21 nano-id chars).
    consecutiveFailuresopcionalinteger
    lastSuccessAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    lastFailureAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    createdAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    updatedAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    JSON
    {  "id": "wbh_uV2aLwzXMqNmKjHbPiRoT",  "organizationId": "org_pGgniw5L7CTDSZDwjDrQ2",  "url": "https://api.partner.test/ccx/webhook",  "secretCipher": "string",  "secretVersion": 1,  "headers": [    {      "key": "X-Api-Key",      "value": "sk_live_…"    }  ],  "events": [    "message.sent"  ],  "status": "active",  "description": "string",  "retry": {    "maxAttempts": 8,    "backoffSeconds": 60  },  "createdById": "acc_dEws32WQG1MgvOVa6wqXT",  "consecutiveFailures": 0,  "lastSuccessAt": "2026-04-07T17:30:00.000Z",  "lastFailureAt": "2026-04-07T17:30:00.000Z",  "createdAt": "2026-04-07T17:30:00.000Z",  "updatedAt": "2026-04-07T17:30:00.000Z"}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 404RFC 7807 problem details for NOT_FOUND (404).

Las respuestas de error siguen el formato RFC 7807 (application/problem+json), con un código estable en el campo code. Ver los códigos de error

Ejemplo en curl

cURL
curl 'https://api.messages.ccxcompany.co/webhooks/wbh_uV2aLwzXMqNmKjHbPiRoT' \  -H "Authorization: Bearer $CCX_API_KEY"
Solo los campos obligatorios. Cambia los valores de ejemplo por los tuyos.

Patch webhook config

PATCH/webhooks/{id}

Partial update. URL is IMMUTABLE — to change the endpoint, delete + recreate (which forces a new secret). status accepts active / paused only; failing / revoked are managed by the Step 19 worker.

Parámetros

CampoDóndeTipoDescripción
idobligatoriorutastringBranded Webhook id (wbh_ prefix + 21 nano-id chars).

Cuerpo de la peticiónapplication/json

CampoTipoDescripción
eventsopcionalstring[]
statusopcionalstringValores:activepaused
descriptionopcionalstring
headersopcionalobject[]Replaces the full custom-header set. [] clears all.
headers[].keyobligatoriostring
headers[].valueobligatoriostring
retryopcionalobject
retry.maxAttemptsobligatoriointeger
retry.backoffSecondsobligatoriointeger
Ejemplo completo del cuerpo
JSON
{  "events": [    "message.sent"  ],  "status": "active",  "description": "string",  "headers": [    {      "key": "X-Api-Key",      "value": "sk_live_…"    }  ],  "retry": {    "maxAttempts": 8,    "backoffSeconds": 60  }}

Respuestas

  • 200Default Response

    Campos y ejemplo de la respuesta
    CampoTipoDescripción
    idobligatoriostringBranded Webhook id (wbh_ prefix + 21 nano-id chars).
    organizationIdobligatoriostringBranded Organization id (org_ prefix + 21 nano-id chars).
    urlobligatoriostring · uri
    secretCipherobligatoriostringPII_CRITICAL — encrypted webhook signing secret (JSON-serialized EncryptedBlob, AAD bound to org+webhook). Never returned in plaintext after creation.
    secretVersionobligatoriointeger
    headersopcionalobject[]
    headers[].keyobligatoriostring
    headers[].valueobligatoriostring
    eventsobligatoriostring[]
    statusobligatoriostringValores:activepausedfailingrevoked
    descriptionopcionalstring
    retryobligatorioobject
    retry.maxAttemptsobligatoriointeger
    retry.backoffSecondsobligatoriointeger
    createdByIdopcionalstringBranded Account id (acc_ prefix + 21 nano-id chars).
    consecutiveFailuresopcionalinteger
    lastSuccessAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    lastFailureAtopcionalstring · date-timeISO-8601 timestamp in UTC.
    createdAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    updatedAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    JSON
    {  "id": "wbh_uV2aLwzXMqNmKjHbPiRoT",  "organizationId": "org_pGgniw5L7CTDSZDwjDrQ2",  "url": "https://api.partner.test/ccx/webhook",  "secretCipher": "string",  "secretVersion": 1,  "headers": [    {      "key": "X-Api-Key",      "value": "sk_live_…"    }  ],  "events": [    "message.sent"  ],  "status": "active",  "description": "string",  "retry": {    "maxAttempts": 8,    "backoffSeconds": 60  },  "createdById": "acc_dEws32WQG1MgvOVa6wqXT",  "consecutiveFailures": 0,  "lastSuccessAt": "2026-04-07T17:30:00.000Z",  "lastFailureAt": "2026-04-07T17:30:00.000Z",  "createdAt": "2026-04-07T17:30:00.000Z",  "updatedAt": "2026-04-07T17:30:00.000Z"}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 404RFC 7807 problem details for NOT_FOUND (404).

  • 422RFC 7807 problem details for VALIDATION_ERROR (422).

Las respuestas de error siguen el formato RFC 7807 (application/problem+json), con un código estable en el campo code. Ver los códigos de error

Ejemplo en curl

cURL
curl -X PATCH 'https://api.messages.ccxcompany.co/webhooks/wbh_uV2aLwzXMqNmKjHbPiRoT' \  -H "Authorization: Bearer $CCX_API_KEY" \  -H "Content-Type: application/json" \  -d '{}'
Solo los campos obligatorios. Cambia los valores de ejemplo por los tuyos.

Delete a webhook subscription

DELETE/webhooks/{id}

Hard delete. The encrypted secret is removed with the row.

Parámetros

CampoDóndeTipoDescripción
idobligatoriorutastringBranded Webhook id (wbh_ prefix + 21 nano-id chars).

Respuestas

  • 204Webhook removed.

  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 404RFC 7807 problem details for NOT_FOUND (404).

Las respuestas de error siguen el formato RFC 7807 (application/problem+json), con un código estable en el campo code. Ver los códigos de error

Ejemplo en curl

cURL
curl -X DELETE 'https://api.messages.ccxcompany.co/webhooks/wbh_uV2aLwzXMqNmKjHbPiRoT' \  -H "Authorization: Bearer $CCX_API_KEY"
Solo los campos obligatorios. Cambia los valores de ejemplo por los tuyos.

Rotate the HMAC signing secret

POST/webhooks/{id}/rotate-secret

Generates a new whsec_… secret, encrypts it with a fresh IV/tag (same AAD binding), bumps secretVersion, and returns the plaintext once. The previous secret is invalid immediately — there is no grace window in Step 13 (Step 19 may add an overlap window for zero-downtime rotation).

Parámetros

CampoDóndeTipoDescripción
idobligatoriorutastringBranded Webhook id (wbh_ prefix + 21 nano-id chars).

Respuestas

  • 200Default Response

    Campos y ejemplo de la respuesta
    CampoTipoDescripción
    idobligatoriostringBranded Webhook id (wbh_ prefix + 21 nano-id chars).
    secretobligatoriostringPlaintext signing secret. Returned once by POST /webhooks and POST /webhooks/:id/rotate-secret. Caller MUST store it — it cannot be retrieved later.
    secretVersionobligatoriointeger
    createdAtobligatoriostring · date-timeISO-8601 timestamp in UTC.
    JSON
    {  "id": "wbh_uV2aLwzXMqNmKjHbPiRoT",  "secret": "whsec_aB3xY9zQ1pTkLmNoPqRsTuVwXyZ123456",  "secretVersion": 1,  "createdAt": "2026-04-07T17:30:00.000Z"}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 404RFC 7807 problem details for NOT_FOUND (404).

Las respuestas de error siguen el formato RFC 7807 (application/problem+json), con un código estable en el campo code. Ver los códigos de error

Ejemplo en curl

cURL
curl -X POST 'https://api.messages.ccxcompany.co/webhooks/wbh_uV2aLwzXMqNmKjHbPiRoT/rotate-secret' \  -H "Authorization: Bearer $CCX_API_KEY"
Solo los campos obligatorios. Cambia los valores de ejemplo por los tuyos.

¿Atascado en una ruta? Habla con quienes mantienen la API.

Si creas la cuenta desde la web, recibes 5 US$ de crédito de prueba.