Listar restricciones de envío
/v1/mail-restrictionsDescripción
Retorna una lista paginada de restricciones de envío: las direcciones que la plataforma no vuelve a contactar. Ordenada por restricted_at descendente.
Esta es la lista de supresión completa, indexada por dirección de correo: no está acotada por la ventana de retención, así que una restricción de hace un año sigue siendo consultable. Para responder "¿esta dirección está suprimida?", este es el endpoint. Ver Estado y evento para la diferencia con mail-unsubscribes.
Solo lectura: la API pública no expone alta ni baja de restricciones.
Autenticación
Authorizationbearer tokenheaderobligatorio- API key con scope
mail:read. Formato:Bearer FD.<key_id>.<token>. X-Instance-Slugstringheaderobligatorio
Request
Query params:
pageinteger- Página, 1-indexed. Default: 1.
page_sizeinteger- Tamaño de página, 1–100. Default: 20.
recipientstring | null- Filtra por email del destinatario - coincidencia parcial, insensible a mayúsculas. Ver Filtros de texto.
reasonstring | null- Filtra por motivo (ver vocabulario). Un valor fuera del vocabulario retorna
422. activeboolean | nulltrue: solo restricciones vigentes.false: solo restricciones levantadas. Omitido: todas.
Response
data con los elementos y pagination para pedir la siguiente. Cada elemento tiene los campos que siguen.idintegerobligatorio- Identificador de la restricción.
recipientstringobligatorio- Email del destinatario restringido.
reasonstring | null- Motivo, ver vocabulario.
scopestring | null- Reservado. Hoy siempre
null; no construyas lógica sobre este campo. restricted_atstring (date-time) | null- Fecha y hora en que se aplicó la restricción.
deleted_atstring (date-time) | null- Fecha y hora en que se levantó la restricción.
nullsi sigue vigente.
Errores
| Código | Cuándo |
|---|---|
| 403 | La API key no tiene el scope mail:read, o la IP del cliente no está en la lista permitida. |
| 422 | reason fuera del vocabulario (validation_error; el detalle por campo viene en errors[] con code: "enum", ver errores por campo). |
Vocabulario de reason
| Valor | Significado |
|---|---|
unspecified | Sin motivo registrado. Parte del vocabulario; hoy ningún productor lo emite. |
unsubscribe | El destinatario se desuscribió. |
soft_bounce | Acumuló rebotes transitorios hasta cruzar el umbral configurado. |
hard_bounce | Rebote permanente: la dirección no existe o rechaza de forma definitiva. |
Estado y evento
Son dos cosas distintas y se consultan por endpoints distintos:
mail-restrictions | mail-unsubscribes | |
|---|---|---|
| Qué es | El estado de supresión de una dirección | El log de eventos de desuscripción |
| Indexado por | Dirección de correo | Correo (mail_id): una fila por correo, no por evento |
| Mutable | Sí: se levanta al resuscribirse | Solo se enriquece: se conserva la primera desuscripción del correo y se completan el motivo o el comentario si llegan después |
| Ventana | Completa, sin corte de retención | Acotada por la retención del correo asociado |
Una desuscripción genera las dos cosas: la fila del evento y la restricción correspondiente (reason: "unsubscribe"). Al resuscribirse se levanta la restricción, que pasa a exponer deleted_at, y el evento original no se toca.
Consecuencia práctica: para saber si una dirección está suprimida, consulta este endpoint, no el de desuscripciones. Una queja (mail-complaints), en cambio, no genera restricción por sí sola.
- El vocabulario de
reasones abierto. Pueden aparecer valores nuevos sin aviso previo. Trata un valor desconocido con un caso por defecto en lugar de unswitchexhaustivo; un valor nuevo no es un cambio incompatible. - El filtro
recipientes de coincidencia parcial, así que sirve para higiene por dominio (?recipient=@acme.comlista todo lo de ese dominio). El reverso: consultar porana@ejemplo.comtambién devuelve amariana@ejemplo.com.mx, así que para decidir si una dirección puntual está suprimida hay que comparar la dirección devuelta, no confiar en que haya resultados. - Una dirección con
+debe ir percent-encodeada como%2B. En una query string el+se decodifica como espacio, así que enviarlo tal cual buscausuario tag@ejemplo.com, no matchea nada y la respuesta es un200con lista vacía - falla en silencio. Correcto:?recipient=usuario%2Btag@ejemplo.com. Ver Filtros de texto.
curl -X GET "https://$API_HOST/v1/mail-restrictions?active=true&reason=hard_bounce" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG"
{
"data": [
{
"id": 5,
"recipient": "bob@example.com",
"reason": "hard_bounce",
"scope": null,
"restricted_at": "2026-05-10T09:00:00Z",
"deleted_at": null
}
],
"pagination": {
"page": 1,
"page_size": 20,
"has_more": false,
"total_items": 1,
"total_pages": 1
}
}