Saltar al contenido principal

Registrar una restricción de envío

POST/v1/mail-restrictions

Para desarrolladores

Descripción​

Registra una oposición o un bloqueo temporal sobre una dirección de correo. Desde ese momento ningún remitente de la instancia le envía los correos que la restricción cubre, sin importar si el envío viene de la API, del relay SMTP o del panel.

Oposición (objection)Bloqueo temporal (block)
Para quéEl destinatario se opone a recibir correosDetener todo envío mientras se resuelve una solicitud del destinatario (por ejemplo, una rectificación)
Qué envíos detieneLos que indica scope: masivo, transaccional o ambosTodos
Fecha de términoNo aceptaOpcional, en expires_at; al llegar, el bloqueo se levanta automáticamente
Cómo se levantaNo se levanta: es permanenteAl llegar expires_at, o desde la Ficha de contacto del panel

La API no levanta ninguna de las dos. Por eso, en un bloqueo indique siempre expires_at: sin fecha de término, el bloqueo solo se levanta desde el panel.

Cada llamada registra una dirección. No hay una forma por lotes de este endpoint.

Cada registro queda en el log de actividad de la instancia, a nombre de la API key que lo hizo.

Guía relacionada​

  • Ficha de contacto — Registre desde el panel la oposición o el bloqueo de un contacto.

Autenticación​

Authorizationbearer tokenheaderobligatorio
API key con scope mail:restrict. Formato: Bearer <API_KEY>.
X-Instance-Slugstringheaderobligatorio
Identificador de su instancia. Ver Autenticación.

Una API key de Acceso completo incluye el scope mail:restrict. Una API key con Permisos específicos lo tiene solo si se le seleccionó Registrar oposiciones y bloqueos: ningún otro permiso lo incluye, tampoco mail:read.

Request​

Query params:

tzstring
Zona horaria IANA (por ejemplo, America/Santiago) con que se interpreta un expires_at sin zona horaria. Sin valor se usa la zona de la instancia; si la instancia no tiene zona, UTC. Es la misma regla de los reportes.

Body:

recipientstringobligatorio
Email del destinatario, de 3 a 254 caracteres. Se guarda en minúsculas.
reasonstringobligatorio
objection o block.
scopearray de string
Qué envíos detiene la oposición: masivo, transaccional o ambos. Obligatorio en objection; no se acepta en block.
expires_atstring (date-time)
Fin del bloqueo, ISO 8601. Con zona horaria se usa tal cual; sin zona se interpreta en la zona de tz o, en su defecto, en la de la instancia. Solo en block. Debe ser futura y anterior al 19-01-2038.

Un campo que el body no declara se ignora.

Response​

201 CreatedCon el header Location: /v1/mail-restrictions/{id}.

La respuesta tiene la misma forma que cada elemento de GET /v1/mail-restrictions.

idintegersiempre presente
Identificador de la restricción.
recipientstringsiempre presente
Email del destinatario restringido.
reasonstring | null
Motivo, ver vocabulario.
scopearray de string | null
Qué envíos bloquea la restricción: masivo, transaccional o ambos. null bloquea todo envío. Ver Alcance de una restricción.
restricted_atstring (date-time) | null
Fecha y hora en que se aplicó la restricción.
expires_atstring (date-time) | null
Fin previsto de un bloqueo temporal (reason: block). Al pasar esa fecha, la restricción se levanta automáticamente y pasa a exponer deleted_at. null en cualquier otro motivo, y en un bloqueo sin fecha de término.
deleted_atstring (date-time) | null
Fecha y hora en que se levantó la restricción. null si sigue vigente.

Errores​

CódigocodeCuándo
403forbidden / ip_not_allowedLa API key no tiene el scope mail:restrict, o la IP del cliente no está en la lista permitida.
409contact_objection_existsLas oposiciones vigentes de la dirección ya cubren todos los tipos de envío pedidos. Una oposición que agrega un tipo que ninguna cubre sí se registra.
409contact_block_existsLa dirección ya tiene un bloqueo temporal vigente: solo puede haber uno por dirección.
422validation_errorEl body no cumple el contrato. El detalle por campo viene en errors[] (ver errores por campo).

Valores de errors[].code propios de este endpoint, todos en /expires_at:

codeCuándo
expires_at_not_futureLa fecha de término no es futura.
expires_at_nonexistentLa fecha de término, sin zona horaria, cae en una hora que esa zona se salta por el cambio de horario.
expires_at_out_of_rangeLa fecha de término es posterior al 19-01-2038.
expires_at_block_onlySe indicó una fecha de término en una oposición.

Un scope ausente en objection, o presente en block, responde 422, y en errors[] el error llega con code: "value_error" y pointer: "" (la raíz del body).

Oposición y consentimiento​

Una oposición y un rechazo de consentimiento (una regla deny en POST /v1/consent-events) no son lo mismo:

  • La oposición detiene todo remitente de los tipos de envío que cubre, tenga o no la instancia el módulo de consentimiento y exija o no el remitente una finalidad.
  • Un rechazo de consentimiento es por finalidad: detiene solo los envíos de los remitentes que exigen esa finalidad.

Si el destinatario pide no recibir más correos de la instancia, registre una oposición. Si retira su consentimiento para un fin concreto (por ejemplo, marketing), registre el rechazo de esa finalidad.

Notas
  • Una oposición es permanente. Ni siquiera el panel la levanta, así que verifique la dirección antes de registrarla.
  • Se ve en el listado. El registro aparece de inmediato en GET /v1/mail-restrictions, con reason objection o block.
  • El enlace para volver a suscribirse no levanta una oposición ni un bloqueo: solo levanta las desuscripciones.
Request
curl -X POST "https://$API_HOST/v1/mail-restrictions" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
-H "Content-Type: application/json" \
-d '{
"recipient": "[email protected]",
"reason": "block",
"expires_at": "2026-11-20T12:00:00-03:00"
}'
Response
{
"id": 42,
"recipient": "[email protected]",
"reason": "block",
"scope": [
"masivo",
"transaccional"
],
"restricted_at": "2026-10-20T15:04:05Z",
"expires_at": "2026-11-20T15:00:00Z",
"deleted_at": null
}