Saltar al contenido principal

API de supresiones

La API de supresiones gestiona las listas, por espacio de trabajo, de direcciones de email y números de teléfono a los que Joryio no enviará mensajes. Una supresión es un bloqueo estricto: mientras un identificador esté suprimido en un canal, se omite cualquier mensaje a ese identificador en ese canal, sin importar qué campaña o journey intente alcanzarlo.

Esta API refleja la sección Audiencia → Listas de supresión del dashboard. Úsala para auditar quién está suprimido, migrar una lista existente de direcciones inactivas desde otra plataforma, cumplir una solicitud de consentimiento de tus propios sistemas o eliminar una supresión después de resolver un rebote permanente.

Todos los endpoints de esta página son relativos a la URL base: https://api-eu1.joryio.com. Consulta el resumen de la API.

Autenticación

Cada solicitud se autentica con una clave de API que tenga el scope de entregabilidad correspondiente o con una sesión del dashboard (JWT). Los datos de supresión tienen ámbito de espacio de trabajo: una clave solo puede ver y editar las listas de su propio espacio de trabajo.

Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json

Scopes por endpoint

El canal determina el scope necesario. Los endpoints de email necesitan email_suppression:*; los de SMS y WhatsApp necesitan sms_suppression:*.

EndpointCanal emailCanal SMS / WhatsApp
GET /suppressionsemail_suppression:readsms_suppression:read
GET /suppressions/{identifier}email_suppression:readsms_suppression:read
POST /suppressionsemail_suppression:writesms_suppression:write
POST /suppressions/hard-bounceemail_suppression:write- (email only)
POST /suppressions/importemail_suppression:writesms_suppression:write
DELETE /suppressions/{identifier}email_suppression:writesms_suppression:write

Conceptos básicos

Lee esta sección antes de llamar a los endpoints de escritura: el resto de la API solo tiene sentido una vez que está clara la separación entre reason y source.

reason (por qué) frente a source (de dónde procede)

Cada fila de supresión tiene dos campos independientes:

  • reason: por qué se suprime el identificador. Puede ser unsubscribe, hard_bounce, complaint o manual.
  • source: de dónde procede la supresión. Puede ser delivery, api, import o una fuente de consentimiento como unsubscribe_link.

Son conceptos independientes. Un mismo reason puede provenir de fuentes distintas: un hard_bounce observado por nuestra propia canalización de envío tiene source: "delivery", mientras que un hard_bounce que declares mediante esta API tiene source: "api". El motivo indica su significado de entregabilidad o consentimiento; la fuente te dice en qué medida confiar en él y si cuenta para tus métricas de reputación.

Motivos de consentimiento frente a motivos de entregabilidad

Los cuatro motivos se dividen en dos familias que se comportan de forma diferente:

FamiliaMotivosSignificado¿Sobrevive a una nueva suscripción?
Consentimientounsubscribe, manualEl destinatario, o tú en su nombre, pidió no recibir comunicaciones.No: una nueva aceptación lo elimina.
Entregabilidadhard_bounce, complaintLa dirección o el número ya no es válido o nos marcó como spam.Sí: persiste incluso si el destinatario vuelve a suscribirse.

Una supresión de entregabilidad es un hecho técnico sobre la dirección, no una preferencia; por eso, que el destinatario se suscriba de nuevo no la elimina. Solo se elimina mediante una acción explícita del operador: DELETE /suppressions/{identifier}, «borrar rebote» en el dashboard o el cambio del contacto a una dirección de email nueva.

No se puede inventar un rebote

Las rutas de escritura habituales, POST /suppressions y POST /suppressions/import, restringen reason a manual o unsubscribe. No pueden crear una fila hard_bounce ni complaint. Un rebote es algo que la plataforma observa, no algo que un cliente pueda declarar sin más.

La única ruta que puede declarar un rebote es POST /suppressions/hard-bounce y, aun así, la fila lleva source: "api", para que nunca se confunda con un rebote observado por nosotros.

Solo los rebotes reales afectan a tu reputación

La tasa de rebotes declarada de tu cuenta y las métricas de entregabilidad o reputación cuentan solo los rebotes con source: "delivery", es decir, los que nuestra propia canalización de envío observó en la capa SMTP. Una supresión declarada por API (source: "api") o importada (source: "import") bloquea el envío a ese identificador, pero no eleva tu tasa de rebotes declarada. Así puedes proteger la reputación de tu remitente cargando previamente direcciones que sabes que no sirven, sin contaminar la métrica que quieres proteger.

La supresión sigue a la dirección o el número

Una supresión se vincula a la dirección de email o el número de teléfono normalizado dentro del espacio de trabajo, no a un registro de contacto. Por eso, una dirección suprimida cubre a todos los contactos duplicados que la compartan. Suprime jane@example.com una vez y todos los contactos con esa dirección quedan bloqueados en email en todo el espacio de trabajo.


Referencia de reason / source

Valores de reason

reasonFamiliaCreado por
unsubscribeConsentimientoEnlace de baja del destinatario, POST /suppressions, POST /suppressions/import
manualConsentimientoAcción de operador, POST /suppressions, POST /suppressions/import
hard_bounceEntregabilidadNuestra canalización de envío, POST /suppressions/hard-bounce
complaintEntregabilidadNuestra canalización de envío (bucles de comentarios)

Valores de source

sourceSignificado¿Cuenta para la reputación?
deliveryObservado por nuestra propia canalización de envío/recepción (rebote real o queja).
apiDeclarado mediante esta API REST.No
importCargado mediante POST /suppressions/import (migración masiva).No
unsubscribe_link (y otras fuentes de consentimiento)Cambio de consentimiento iniciado por el destinatario.No

Listar supresiones

Devuelve una lista paginada de identificadores suprimidos de un canal.

Endpoint

GET /suppressions

Parámetros de consulta

ParámetroTipoPredeterminadoDescripción
channelcadena-email, sms o whatsapp. Obligatorio.
reasoncadena-Filtro opcional: unsubscribe, hard_bounce, complaint o manual.
limitnúmero100Filas por página, máximo 1000.
offsetnúmero0Desplazamiento de paginación.

Solicitud de ejemplo

curl -X GET "https://api-eu1.joryio.com/suppressions?channel=email&reason=hard_bounce&limit=50" \
-H "Authorization: Bearer jry_live_your_api_key"

Respuesta

{
"items": [
{
"identifier": "dead-address@example.com",
"channel": "email",
"identifierType": "email",
"reason": "hard_bounce",
"source": "delivery",
"scope": "global",
"listId": null,
"createdAt": "2026-06-30T12:04:11.000Z"
},
{
"identifier": "jane@example.com",
"channel": "email",
"identifierType": "email",
"reason": "unsubscribe",
"source": "unsubscribe_link",
"scope": "group",
"listId": "grp_newsletter",
"createdAt": "2026-07-02T09:20:00.000Z"
}
],
"total": 214,
"limit": 50,
"offset": 0
}

Comprobar un identificador

Comprueba si un identificador concreto está suprimido en un canal.

Endpoint

GET /suppressions/{identifier}

El parámetro de ruta {identifier} es la dirección de email o el número de teléfono codificado para URL.

Parámetros de consulta

ParámetroTipoPredeterminadoDescripción
channelcadena-email, sms o whatsapp. Obligatorio.

Solicitud de ejemplo

curl -X GET "https://api-eu1.joryio.com/suppressions/dead-address@example.com?channel=email" \
-H "Authorization: Bearer jry_live_your_api_key"

Respuesta: suprimido

{
"suppressed": true,
"identifier": "dead-address@example.com",
"reason": "hard_bounce",
"source": "delivery",
"scope": "global",
"listId": null,
"createdAt": "2026-06-30T12:04:11.000Z"
}

Respuesta: no suprimido

{
"suppressed": false
}

Añadir una supresión

Añade una supresión por consentimiento o manual. Úsala para respetar una baja que te haya llegado por tus propios sistemas, como un ticket de soporte, una marca del CRM o un cambio en tu propio centro de preferencias.

Endpoint

POST /suppressions

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
channelcadenaemail, sms o whatsapp.
identifiercadenaDirección de email o número de teléfono que se suprimirá.
reasoncadenaNomanual (predeterminado) o unsubscribe. Restringido: se rechaza cualquier otro valor.
scopecadenaNoglobal (predeterminado) o group.
listIdcadenaNoObligatorio si scope es group: grupo/lista al que se aplica esta supresión.

El source de una fila creada aquí siempre se registra como api. Este endpoint no puede crear un hard_bounce ni una complaint.

Solicitud de ejemplo

curl -X POST https://api-eu1.joryio.com/suppressions \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channel": "email",
"identifier": "jane@example.com",
"reason": "unsubscribe",
"scope": "group",
"listId": "grp_newsletter"
}'

Respuesta

{
"identifier": "jane@example.com",
"channel": "email",
"identifierType": "email",
"reason": "unsubscribe",
"source": "api",
"scope": "group",
"listId": "grp_newsletter",
"createdAt": "2026-07-11T08:15:00.000Z"
}

Declarar un rebote permanente

Registra un rebote permanente de una dirección de email. Es la única ruta de API que puede declarar una supresión de entregabilidad, y está separada y restringida de forma intencionada.

Por qué este endpoint está separado

  • Un rebote es normalmente algo que Joryio observa al enviar, no algo que declare quien llama. Mantener esa declaración fuera de las rutas habituales de añadir/importar evita creaciones accidentales o descuidadas.
  • Como lo estás declarando tú y no observándolo nosotros, la fila lleva source: "api". Bloquea el envío igual que un rebote real, pero nunca se confunde con uno que hayamos visto y no cuenta para tu tasa de rebotes declarada ni tus métricas de reputación de remitente.
  • Es solo para email. No existe equivalente para teléfono: la falta de entrega de SMS/WhatsApp se modela de otra manera.

Endpoint

POST /suppressions/hard-bounce

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
identifiercadenaDirección de email que tuvo el rebote permanente.

El canal es implícitamente email. La fila se registra con reason: "hard_bounce" y source: "api".

Solicitud de ejemplo

curl -X POST https://api-eu1.joryio.com/suppressions/hard-bounce \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"identifier": "no-such-mailbox@example.com"
}'

Respuesta

{
"identifier": "no-such-mailbox@example.com",
"channel": "email",
"identifierType": "email",
"reason": "hard_bounce",
"source": "api",
"scope": "global",
"listId": null,
"createdAt": "2026-07-11T08:20:00.000Z"
}

Importación masiva

Carga una lista de supresiones existente, por ejemplo al migrar desde otra plataforma.

Endpoint

POST /suppressions/import

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
channelcadenaemail, sms o whatsapp.
entriesmatrizHasta 5000 objetos, cada uno { identifier, reason? }.

El reason de cada entrada se restringe a manual (predeterminado) o unsubscribe; cualquier otro valor se convierte en manual. Cada fila importada se registra con source: "import". Igual que el endpoint de añadir, la importación no puede crear un rebote ni una queja.

Solicitud de ejemplo

curl -X POST https://api-eu1.joryio.com/suppressions/import \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channel": "email",
"entries": [
{ "identifier": "old-dead-1@example.com" },
{ "identifier": "opted-out@example.com", "reason": "unsubscribe" },
{ "identifier": "old-dead-2@example.com" }
]
}'

Respuesta

{
"channel": "email",
"received": 3,
"imported": 3,
"skipped": 0,
"source": "import"
}

Eliminar una supresión (anular supresión)

Elimina una supresión para que Joryio pueda volver a enviar al identificador.

Endpoint

DELETE /suppressions/{identifier}

Parámetros de consulta

ParámetroTipoPredeterminadoDescripción
channelcadena-email, sms o whatsapp. Obligatorio.
aviso

Esto elimina todas las filas de supresión del identificador en ese canal y espacio de trabajo, incluida una fila de entregabilidad hard_bounce o complaint. Es una eliminación deliberada por parte del operador o la API: anular la supresión de una dirección es precisamente cómo se borra un rebote permanente resuelto. Elimina una supresión de entregabilidad solo cuando sepas que el problema subyacente está solucionado, o correrás el riesgo de enviar a una dirección inactiva y dañar la reputación de tu remitente.

Solicitud de ejemplo

curl -X DELETE "https://api-eu1.joryio.com/suppressions/no-such-mailbox@example.com?channel=email" \
-H "Authorization: Bearer jry_live_your_api_key"

Respuesta

{
"identifier": "no-such-mailbox@example.com",
"removed": 2
}

removed es el número de filas de supresión eliminadas; un identificador puede tener a la vez una fila de consentimiento de ámbito de grupo y una fila global de entregabilidad.


Migrar una lista de supresiones existente

Cuando pases a Joryio desde otra plataforma de email o SMS, lleva tu lista de supresiones desde el primer día para que tu primer envío no vuelva a contactar direcciones que ya sabes que no sirven o que se dieron de baja.

  1. Importa la lista completa mediante POST /suppressions/import. Las entradas llegan como manual - o unsubscribe si las etiquetas así - con source: "import". Bloquean el envío y protegen la reputación de tu remitente desde el primer envío, sin aumentar tu tasa de rebotes declarada, porque las filas importadas nunca cuentan para la reputación.
  2. Solo si necesitas específicamente que esas direcciones se informen como rebotes, por ejemplo para mantener continua la analítica de rebotes durante la migración, decláralas de una en una con POST /suppressions/hard-bounce. Seguirán llevando source: "api", por lo que bloquean el envío y aparecen como rebotes en la lista de supresiones sin contarse como rebotes observados por nosotros.

Para la mayoría de las migraciones, solo el paso 1 es lo correcto: detiene los envíos y mantiene limpias tus métricas de reputación.


Respuestas de error

Todos los errores comparten la estructura estándar: no existe un vocabulario separado de códigos de error legibles por máquina; usa el estado HTTP junto con el campo message. Consulta respuesta de error en el resumen de la API. Los errores de validación (400) añaden una matriz errors con un mensaje por cada campo que falla:

{
"statusCode": 400,
"message": "Bad Request Exception",
"timestamp": "2026-07-12T09:00:00.000Z",
"path": "/suppressions",
"errors": [
"reason must be one of the following values: manual, unsubscribe"
]
}

Importante: esta API aplica scopes específicos de cada canal. Una clave de API que solo tiene el scope de SMS recibe un 403 si accede a supresiones de email, y viceversa:

{
"statusCode": 403,
"message": "API key missing required scope 'email_suppression:write' for channel 'email'",
"timestamp": "2026-07-12T09:00:00.000Z",
"path": "/suppressions"
}

Siguientes pasos