Saltar al contenido principal

Listar restricciones de envío

GET/v1/mail-restrictions

Descripció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 | null
true: solo restricciones vigentes. false: solo restricciones levantadas. Omitido: todas.

Response

200 OKDevuelve una página de resultados: 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. null si sigue vigente.

Errores

CódigoCuándo
403La API key no tiene el scope mail:read, o la IP del cliente no está en la lista permitida.
422reason fuera del vocabulario (validation_error; el detalle por campo viene en errors[] con code: "enum", ver errores por campo).

Vocabulario de reason

ValorSignificado
unspecifiedSin motivo registrado. Parte del vocabulario; hoy ningún productor lo emite.
unsubscribeEl destinatario se desuscribió.
soft_bounceAcumuló rebotes transitorios hasta cruzar el umbral configurado.
hard_bounceRebote 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-restrictionsmail-unsubscribes
Qué esEl estado de supresión de una direcciónEl log de eventos de desuscripción
Indexado porDirección de correoCorreo (mail_id): una fila por correo, no por evento
MutableSí: se levanta al resuscribirseSolo se enriquece: se conserva la primera desuscripción del correo y se completan el motivo o el comentario si llegan después
VentanaCompleta, sin corte de retenciónAcotada 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.

Notas
  • El vocabulario de reason es abierto. Pueden aparecer valores nuevos sin aviso previo. Trata un valor desconocido con un caso por defecto en lugar de un switch exhaustivo; un valor nuevo no es un cambio incompatible.
  • El filtro recipient es de coincidencia parcial, así que sirve para higiene por dominio (?recipient=@acme.com lista todo lo de ese dominio). El reverso: consultar por ana@ejemplo.com también devuelve a mariana@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 busca usuario tag@ejemplo.com, no matchea nada y la respuesta es un 200 con lista vacía - falla en silencio. Correcto: ?recipient=usuario%2Btag@ejemplo.com. Ver Filtros de texto.
Request
curl -X GET "https://$API_HOST/v1/mail-restrictions?active=true&reason=hard_bounce" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG"
Response
{
"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
}
}