Recibir correos (Inbound)
Recibe correos en tu app: activa la recepción en el dominio, crea direcciones o un catch-all, procesa el webhook email.received y obtén el contenido, los adjuntos y el original por la API.
#Cómo funciona
Inbound es recibir y procesar correos en tu propio sistema: una dirección tuya recibe el mensaje, Postal guarda el texto, el HTML, los adjuntos y el original, avisa a tu código por el webhook email.received y entrega el contenido por la API. No hace falta mantener un servidor de correo. Conoce la página de Inbound.
- Quien escribe envía el mensaje a una dirección tuya (en tu dominio, con el MX apuntando a
mx.postal.so, o en una dirección generada enin.postal.so). - El servidor de entrada de Postal acepta el mensaje solo si existe un buzón de entrada para esa dirección.
- Postal guarda el mensaje y los adjuntos y crea un
received_email, uno por cada buzón de destino. - Cada webhook del equipo suscrito a
email.receivedrecibe un POST firmado con el resumen. - Tu código obtiene el contenido con
GET /emails/receiving/{id}y hace lo que necesita: abre un ticket, guarda un adjunto, responde.
Inbound y buzones de entrada
Es el mismo recurso. Los mensajes que procesa tu código también aparecen en Buzones de entrada, en el panel, organizados en conversaciones. Usa Inbound cuando quien trabaja es tu código, y los buzones de entrada cuando personas del equipo leen y responden. Los dos funcionan a la vez.
#Planes y disponibilidad
El plan define cuántos buzones de entrada puede tener el equipo y si pueden usar un dominio tuyo. En el plan Gratis, hasta 3 buzones, todos con dirección en in.postal.so. Las direcciones en tu dominio, catch-all incluido, y la activación de la recepción en el dominio son de los planes de pago (custom_inbound_domains).
| Gratis | Profesional | Escala | Empresarial | |
|---|---|---|---|---|
| Buzones de entrada | 3 | 10 | 100 | Sin límite |
| Buzones de entrada en tu dominio | No | Sí | Sí | Sí |
Valores actualizados desde GET /plans al abrir la página.
Recibir no usa la cuota de envíos del plan. Las respuestas y los reenvíos salen como envíos normales y cuentan en la cuota. Pasar del número de buzones responde 403 plan_limit_reached; consulta Límites del plan y Recursos por plan.
#Recibir en tu dominio
Activa la recepción en el dominio en el panel (Dominios, pestaña de configuración, Recepción (buzones de entrada)) o por la API, con capabilities.receiving en PATCH /domains/{id} (o al registrarlo, en POST /domains):
cURL
curl -X PATCH https://api.postal.so/domains/0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f \
-H "Authorization: Bearer $POSTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"capabilities": {
"receiving": "enabled"
}
}'
Node.js
const response = await fetch('https://api.postal.so/domains/0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
capabilities: {
receiving: 'enabled',
},
}),
});
const data = await response.json();
Python
import os
import requests
response = requests.patch(
"https://api.postal.so/domains/0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
json={
"capabilities": {
"receiving": "enabled",
},
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->patch('domains/0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'json' => [
'capabilities' => [
'receiving' => 'enabled',
],
],
]);
$data = json_decode($response->getBody(), true);
Después, crea en el DNS del dominio el registro que pide Postal:
| Tipo | Nombre | Valor | Prioridad |
|---|---|---|---|
MX | @ | mx.postal.so | 10 |
El nombre @ es el propio dominio registrado: para respostas.lojaexemplo.com.br, el MX va en respostas.lojaexemplo.com.br. La recepción no depende de la verificación de envío (DKIM y SPF): los mensajes llegan en cuanto el MX apunta a Postal. Un dominio puede incluso ser solo de recepción, con capabilities.sending en disabled. Responder y reenviar desde el dominio, en cambio, exigen el dominio verificado para envío.
Usa un subdominio si el dominio ya recibe correos
El MX decide adónde van todos los correos del dominio. Si lojaexemplo.com.br ya recibe en Google Workspace o en Microsoft 365, cambiar el MX saca los mensajes de allí. Registra un subdominio, como respostas.lojaexemplo.com.br, y activa la recepción en él. Para saber si el dominio ya tiene MX de otro proveedor, consulta GET /domains/{id}/receiving-check: solo informa, no bloquea, y el panel usa la respuesta para avisar antes de activar.
Más detalles sobre el DNS en Dominios y DNS.
#Direcciones y catch-all
Cada dirección que recibe es un buzón de entrada. Créalo en el panel, en Buzones de entrada, o con POST /inboxes. Hay tres tipos:
| Tipo | Cómo crearlo | Ejemplo |
|---|---|---|
| Dirección exacta | domain_id y local_part | [email protected] |
| Catch-all | domain_id y local_part igual a * | *@respostas.lojaexemplo.com.br |
| Dirección generada | Sin domain_id: Postal genera la dirección (también en el plan Gratis) | [email protected] |
cURL
curl -X POST https://api.postal.so/inboxes \
-H "Authorization: Bearer $POSTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Respostas",
"domain_id": "0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f",
"local_part": "*"
}'
Node.js
const response = await fetch('https://api.postal.so/inboxes', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Respostas',
domain_id: '0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f',
local_part: '*',
}),
});
const data = await response.json();
Python
import os
import requests
response = requests.post(
"https://api.postal.so/inboxes",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
json={
"name": "Respostas",
"domain_id": "0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f",
"local_part": "*",
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->post('inboxes', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'json' => [
'name' => 'Respostas',
'domain_id' => '0199f0e1-2a3b-7c4d-8e5f-6a7b8c9d0e1f',
'local_part' => '*',
],
]);
$data = json_decode($response->getBody(), true);
Cuando llega un mensaje, Postal busca el buzón en este orden: la dirección de recepción en in.postal.so de un buzón (receiving_address), la dirección exacta y, por último, el catch-all del dominio. La dirección exacta gana al catch-all. Las direcciones se comparan sin distinguir mayúsculas y minúsculas y son únicas en todo Postal.
- Sin tratamiento especial para
+:suporte+pedido@solo llega si existe un buzón con esa dirección exacta o un catch-all en el dominio. Para una dirección por pedido o por conversación, usa el catch-all. - Reenviar desde otro proveedor, sin cambiar el MX: cada buzón de dirección exacta en tu dominio recibe también una
receiving_addressenin.postal.so. Configura tu proveedor actual para reenviar a ella y los mensajes llegan al buzón. El catch-all no tiene esa dirección. - Un mensaje para dos buzones se convierte en dos correos recibidos y dos eventos, uno por buzón. Dos veces el mismo buzón (por ejemplo, en
toy encc) da uno solo.
#El webhook email.received
Registra la URL de tu sistema en Webhooks, en el panel, y marca Recibido, o créalo con POST /webhooks. La URL debe ser HTTPS y pública. Guarda el signing_secret (whsec_…) de la respuesta: con él se comprueba la firma.
cURL
curl -X POST https://api.postal.so/webhooks \
-H "Authorization: Bearer $POSTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"endpoint": "https://lojaexemplo.com.br/webhooks/postal",
"events": ["email.received"]
}'
Node.js
const response = await fetch('https://api.postal.so/webhooks', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
endpoint: 'https://lojaexemplo.com.br/webhooks/postal',
events: ['email.received'],
}),
});
const data = await response.json();
Python
import os
import requests
response = requests.post(
"https://api.postal.so/webhooks",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
json={
"endpoint": "https://lojaexemplo.com.br/webhooks/postal",
"events": ["email.received"],
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->post('webhooks', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'json' => [
'endpoint' => 'https://lojaexemplo.com.br/webhooks/postal',
'events' => ['email.received'],
],
]);
$data = json_decode($response->getBody(), true);
En cuanto guarda el mensaje, Postal envía un POST con este cuerpo:
{
"type": "email.received",
"created_at": "2026-11-04T12:41:09.880Z",
"data": {
"email_id": "019a1c00-3e4f-7a5b-9c6d-7e8f9a0b1c2d",
"inbox_id": "0199f5c1-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
"thread_id": "019a1c00-5a10-7d11-8e22-0f1a2b3c4d5e",
"created_at": "2026-11-04T12:41:09.000Z",
"from": "Bruno Lima <[email protected]>",
"to": ["[email protected]"],
"cc": [],
"subject": "Nota fiscal do pedido #10475",
"message_id": "[email protected]",
"attachments": [
{
"id": "019a1c00-3e50-7b6c-8d7e-9f0a1b2c3d4e",
"filename": "comprovante-10475.pdf",
"content_type": "application/pdf",
"size": 48213
}
]
}
}
Campo de data | Qué es |
|---|---|
email_id | ID del correo recibido. Úsalo en GET /emails/receiving/{id}. |
inbox_id | El buzón que lo recibió. Un webhook vale para todos los buzones del equipo: filtra por este campo para tratar solo uno. |
thread_id | La conversación: los mensajes que se responden entre sí (por los encabezados In-Reply-To y References) tienen el mismo. |
created_at | Cuándo se recibió el mensaje (ISO 8601, UTC). |
from | El remitente, tal como vino en el encabezado From (con el nombre, si lo hay). |
to, cc | Los destinatarios de los encabezados To y Cc. Un buzón en copia oculta no aparece aquí: usa el inbox_id. |
subject | El asunto. |
message_id | El Message-ID del mensaje, sin los signos < >, o null. |
attachments | id, filename (puede ser null), content_type y size (bytes) de cada adjunto. Sin el contenido. |
El evento no trae el cuerpo ni el otp_token: un webhook pasa por colas, registros y reintentos, y el contenido queda detrás de tu clave de API. Responde con 2xx en hasta 15 segundos; si no, Postal lo intenta de nuevo hasta 8 veces en unas 27 horas, siempre con el mismo webhook-id (úsalo para descartar repeticiones). Consulta Respuestas y reintentos y el historial de entregas.
#Verificar la firma y leer el correo
Cada entrega trae los encabezados webhook-id, webhook-timestamp y webhook-signature (estándar Standard Webhooks, HMAC-SHA256 con el signing_secret; los mismos valores vienen en svix-*). Los SDK comprueban la firma, rechazan mensajes con más de 5 minutos de diferencia y devuelven el evento. El ejemplo de abajo comprueba, responde enseguida y después obtiene el contenido y los adjuntos:
Node.js
import express from 'express';
import { verifyWebhook, PostalWebhookVerificationError } from 'postal-so';
const app = express();
const api = { Authorization: `Bearer ${process.env.POSTAL_API_KEY}` }; // chave de acesso total
// O corpo precisa chegar cru (Buffer) para a assinatura bater.
app.post('/webhooks/postal', express.raw({ type: 'application/json' }), async (req, res) => {
let event;
try {
event = verifyWebhook(req.body, req.headers, process.env.POSTAL_WEBHOOK_SECRET);
} catch (error) {
if (error instanceof PostalWebhookVerificationError) return res.sendStatus(400);
throw error;
}
// Responda logo (até 15 s) e processe numa fila; o webhook-id não muda nas novas tentativas.
res.sendStatus(200);
if (event.type !== 'email.received') return;
const { email_id, inbox_id, from, subject } = event.data;
const email = await fetch(`https://api.postal.so/emails/receiving/${email_id}`, { headers: api })
.then((response) => response.json());
for (const attachment of email.attachments) {
const file = await fetch(attachment.download_url); // link assinado, vale 1 hora
await salvarAnexo(attachment.filename ?? attachment.id, Buffer.from(await file.arrayBuffer()));
}
await abrirChamado({ inbox_id, from, subject, text: email.text, html: email.html });
});
PHP
use Postal\Exceptions\WebhookVerificationException;
use Postal\Webhook;
try {
$event = Webhook::verify(
file_get_contents('php://input'), // corpo cru
getallheaders(),
getenv('POSTAL_WEBHOOK_SECRET'),
);
} catch (WebhookVerificationException $e) {
http_response_code(400);
exit;
}
if ($event['type'] === 'email.received') {
$id = $event['data']['email_id'];
$api = stream_context_create(['http' => [
'header' => 'Authorization: Bearer ' . getenv('POSTAL_API_KEY'), // chave de acesso total
]]);
$email = json_decode(file_get_contents("https://api.postal.so/emails/receiving/{$id}", false, $api), true);
foreach ($email['attachments'] as $attachment) {
$name = basename($attachment['filename'] ?? $attachment['id']);
file_put_contents("/var/anexos/{$id}-{$name}", file_get_contents($attachment['download_url']));
}
abrirChamado($event['data']['from'], $event['data']['subject'], $email['text'], $email['html']);
}
http_response_code(200);
Instala con npm install postal-so o composer require postal-so/postal-php (consulta SDK). Sin SDK, o en otro lenguaje, comprueba la firma como en Verificar la firma, siempre sobre el cuerpo exactamente como llegó.
#Contenido, adjuntos y original
GET /emails/receiving/{id} devuelve el mensaje completo: text, html, reply_to, los encabezados guardados y los adjuntos. Hace falta una clave de API de acceso total; una clave solo de envío recibe 401 restricted_api_key.
cURL
curl https://api.postal.so/emails/receiving/019a1c00-3e4f-7a5b-9c6d-7e8f9a0b1c2d \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/emails/receiving/019a1c00-3e4f-7a5b-9c6d-7e8f9a0b1c2d', {
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.postal.so/emails/receiving/019a1c00-3e4f-7a5b-9c6d-7e8f9a0b1c2d",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->get('emails/receiving/019a1c00-3e4f-7a5b-9c6d-7e8f9a0b1c2d', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
{
"object": "received_email",
"id": "019a1c00-3e4f-7a5b-9c6d-7e8f9a0b1c2d",
"inbox_id": "0199f5c1-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
"created_at": "2026-11-04T12:41:09.000000Z",
"from": "Bruno Lima <[email protected]>",
"to": ["[email protected]"],
"cc": [],
"subject": "Nota fiscal do pedido #10475",
"message_id": "[email protected]",
"read": false,
"size": 66103,
"has_attachments": true,
"otp_token": null,
"reply_to": [],
"html": "<p>Oi! Pode reenviar a nota fiscal do pedido #10475? Segue o comprovante.</p>",
"text": "Oi! Pode reenviar a nota fiscal do pedido #10475? Segue o comprovante.",
"headers": {
"message-id": ["<[email protected]>"],
"date": ["Wed, 4 Nov 2026 09:41:07 -0300"]
},
"attachments": [
{
"id": "019a1c00-3e50-7b6c-8d7e-9f0a1b2c3d4e",
"filename": "comprovante-10475.pdf",
"content_type": "application/pdf",
"content_id": null,
"size": 48213,
"download_url": "https://api.postal.so/received-attachments/019a1c00-3e4f-7a5b-9c6d-7e8f9a0b1c2d/019a1c00-3e50-7b6c-8d7e-9f0a1b2c3d4e?expires=1762263669&signature=5f1c…"
}
]
}
- Adjuntos: cada uno tiene
download_url, un enlace firmado que vale 1 hora y no pide la clave. Pasado el plazo, el enlace responde403: vuelve a obtener el mensaje para un enlace nuevo. Las imágenes incrustadas en el HTML tienencontent_id. - Encabezados:
headersguarda, en listas,message-id,in-reply-to,references,date,list-unsubscribe,auto-submitted,x-postal-forwardedyotp-token, cuando el mensaje los tiene. Los demás están en el original. - Original:
GET /emails/receiving/{id}/rawdevuelve el mensaje exactamente como llegó al servidor (text/plain, RFC 5322), con todos los encabezados y partes MIME. - Códigos de acceso:
otp_tokenes{"code", "origin"}cuando el mensaje tiene un encabezadoOTP-Tokenválido, ynullen los demás casos. Consulta Encabezado OTP-Token, con una prueba de inicio de sesión de punta a punta. - Leídos y no leídos: márcalos con
PATCH /emails/receiving/{id}({"read": true}) para controlar lo que tu código ya procesó.
Sin webhook: consultar la lista
Si tu sistema no recibe webhooks, consulta GET /emails/receiving de vez en cuando, filtrando por buzón y por no leídos, y marca como leído cada mensaje procesado. La lista trae el resumen, del más reciente al más antiguo.
cURL
curl 'https://api.postal.so/emails/receiving?inbox_id=0199f5c1-0a1b-7c2d-8e3f-4a5b6c7d8e9f&unread=true&limit=20' \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/emails/receiving?inbox_id=0199f5c1-0a1b-7c2d-8e3f-4a5b6c7d8e9f&unread=true&limit=20', {
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.postal.so/emails/receiving",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
params={
"inbox_id": "0199f5c1-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
"unread": "true",
"limit": "20",
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->get('emails/receiving', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'query' => [
'inbox_id' => '0199f5c1-0a1b-7c2d-8e3f-4a5b6c7d8e9f',
'unread' => 'true',
'limit' => '20',
],
]);
$data = json_decode($response->getBody(), true);
#Responder y reenviar
Para responder desde tu sistema, envía con POST /emails, desde un dominio verificado, y pasa los encabezados In-Reply-To y References con el message_id recibido entre < >. Así el cliente de correo de quien escribió muestra la respuesta en la misma conversación. Usa el reply_to del mensaje, cuando lo haya, como destinatario.
// email: a resposta de GET /emails/receiving/{id}
const original = `<${email.message_id}>`; // message_id vem sem os sinais < >
await fetch('https://api.postal.so/emails', {
method: 'POST',
headers: { ...api, 'Content-Type': 'application/json' },
body: JSON.stringify({
from: 'Loja Exemplo <[email protected]>',
to: email.reply_to.length ? email.reply_to : [email.from],
subject: email.subject.startsWith('Re:') ? email.subject : `Re: ${email.subject}`,
text: 'Oi, Bruno! Segue a nota fiscal do pedido #10475.',
headers: { 'In-Reply-To': original, References: original },
}),
});
- Por la conversación del buzón: en un buzón de un dominio tuyo verificado,
POST /inboxes/{id}/threads/{thread_id}/replyresponde y guarda la respuesta en la conversación, visible en el panel. Los buzones enin.postal.sosolo reciben. - Reenviar automáticamente:
forward_toen el buzón (hasta 5 direcciones, enPATCH /inboxes/{id}) reenvía cada mensaje nuevo. Solo en buzones de dirección exacta en un dominio tuyo verificado. - Reenviar un mensaje:
POST /emails/receiving/{id}/forward, a hasta 5 direcciones, con las mismas condiciones.
#Límites y retención
| Elemento | Límite | Qué ocurre |
|---|---|---|
| Tamaño del mensaje | 25 MB, con los adjuntos | El servidor lo rechaza en la entrega: 552 5.3.4. |
| Destinatarios por entrega | 50 | Los siguientes reciben 452 4.5.3, y el servidor remitente los entrega en otra conexión. |
| Mensajes por servidor remitente | 60 por minuto, por IP | Aviso temporal 421 4.7.0; el servidor remitente lo intenta de nuevo. |
| Webhook | 2xx en hasta 15 segundos | Hasta 8 intentos en unas 27 horas, con el mismo webhook-id. |
| Enlace de adjunto | 1 hora | Vuelve a obtener el mensaje para un enlace nuevo. |
| Reenvío | 5 direcciones | Solo en buzones de dirección exacta en un dominio verificado. |
| Retención | El plazo del plan (retention_days), 30 días por defecto | El mensaje, los adjuntos y el original se borran en la limpieza nocturna. |
Lo que Postal no hace con lo que llega
Postal no filtra spam ni virus y no verifica ni registra SPF, DKIM ni DMARC de los mensajes recibidos. Tu código recibe todo lo que se envió a una dirección que tiene buzón. Si tu flujo depende de quién lo envió, compruébalo en el original (/raw), trata los adjuntos como archivos no confiables y guarda en tu sistema lo que necesites conservar más allá de la retención.
#Errores y solución de problemas
| Qué ocurre | Causa probable y qué hacer |
|---|---|
Quien envía recibe 550 5.1.1 Recipient address rejected: no such mailbox | No hay buzón para la dirección, o el dominio tiene la recepción desactivada. Crea el buzón (o un catch-all) y revisa capabilities.receiving. |
| Los mensajes siguen llegando a Google o a Microsoft | El dominio todavía tiene otro MX, o el registro nuevo no se propagó. Consulta GET /domains/{id}/receiving-check y prefiere un subdominio. |
552 5.3.4 o 421 4.7.0 en la entrega | Mensaje de más de 25 MB, o más de 60 mensajes por minuto del mismo servidor. El segundo caso es temporal. |
451 4.3.0 Temporary failure en la entrega | Fallo temporal al guardar el mensaje. El servidor remitente lo intenta de nuevo por sí solo. |
403 plan_limit_reached al crear el buzón o activar la recepción | El plan no incluye buzones en tu dominio, o el equipo llegó al número de buzones del plan. |
422 validation_error al crear el buzón | El dominio no tiene la recepción activa, el local_part no es válido o la dirección ya está en uso. |
| El webhook no llega | Comprueba que el endpoint esté suscrito a email.received y activo: un endpoint que falla durante 5 días se desactiva. Los intentos están en Webhooks (GET /webhooks/{id}/events), con el estado y la respuesta de cada uno. |
| La firma no coincide | El cuerpo se leyó como JSON antes de la verificación, el secreto es de otro endpoint o el reloj del servidor está desfasado (más de 5 minutos). |
401 restricted_api_key al leer el mensaje | La clave es solo de envío. Los endpoints de recibidos piden una clave de acceso total. |
403 en el download_url | El enlace tiene más de 1 hora. Vuelve a obtener el mensaje. |
404 al obtener el mensaje | El mensaje se eliminó o pasó la retención, o la clave es de otro equipo. |
Consulta también Errores, la referencia de Recibidos y buzones de entrada y la guía de Webhooks.