Cabeçalhos
Todos os cabeçalhos HTTP que a API PushMesh aceita e emite, incluindo o conjunto proprietário X-Pm-*.
Cabeçalhos
O PushMesh usa um namespace próprio, X-Pm-* (e X-PM-* nas entregas de
webhook). Tudo que não está nesta página é cabeçalho HTTP comum.
Cabeçalhos que a API aceita
| Cabeçalho | Rotas | O que faz |
|---|---|---|
Authorization | rotas autenticadas | Basic pm_live_… (chave do aplicativo) ou Bearer <chave de plataforma> (criação de aplicativo e rotação de chave). Ver Autenticação e erros. |
Content-Type: application/json | rotas com corpo | o corpo é JSON. |
Idempotency-Key | POST /api/v1/notifications | a mesma chave nunca dispara duas campanhas. Vence o idempotency_key do corpo, que por sua vez vence o external_id. |
X-Pm-Priority | POST /api/v1/notifications | transactional (alta) ou marketing (normal). O campo priority do corpo, quando presente, vence o cabeçalho. Valor desconhecido ⇒ 400 nomeado. |
X-Dry-Run: true | POST /api/v1/notifications | ensaio: resolve o alvo e conta os destinatários, mas não persiste, não entrega e não consome a chave de idempotência. |
If-None-Match | GET /api/v1/inapp/pending | se o ETag apresentado ainda vale, a resposta é 304 sem corpo. |
Exemplo: ensaio antes de disparar de verdade
curl -X POST https://api.pushmesh.io/api/v1/notifications \
-H "Authorization: Basic $PUSHMESH_KEY" \
-H "Content-Type: application/json" \
-H "X-Dry-Run: true" \
-d '{
"app_id": "0198e7c4-77a1-7bd2-b0f1-6b1d3f2a9c40",
"included_segments": ["Subscribed Users"],
"contents": { "pt": "Ensaio — nada foi entregue" }
}'
{ "id": "", "recipients": 12840, "dry_run": true }
Cabeçalhos que a API emite
| Cabeçalho | Onde | O que carrega |
|---|---|---|
X-Pm-Request-Id | toda resposta, de sucesso ou de erro | UUIDv7 da requisição. É o mesmo valor de explain.request_id. Guarde-o: é o que correlaciona a sua chamada com o rastro do serviço. |
X-Pm-Lane | POST /api/v1/notifications | a faixa de despacho escolhida: 0 = transacional, 1 = marketing. |
X-Pm-Recipients-Exato | POST /api/v1/notifications | true quando recipients é contagem exata (alvo por identificadores); false quando é estimativa (alvo por segmento). |
X-Idempotent-Replay | POST /api/v1/notifications | presente e true somente quando a resposta é a repetição byte a byte de uma chamada anterior com a mesma Idempotency-Key. |
ETag | GET /api/v1/inapp/pending | impressão digital do pacote In-App. Devolva em If-None-Match na próxima sessão. O corpo repete o valor no campo etag. |
Retry-After | 429 das rotas do aparelho | segundos a esperar (60). Ver a nota em Limites. |
X-Pm-Instance | respostas que passam pela borda | identificador da instância que atendeu — informação de suporte. |
Como ler o resultado de um envio pelos cabeçalhos
HTTP/1.1 200 OK
X-Pm-Request-Id: 0198f0b2-6e31-7a4c-9f10-2c9a1d4e7b55
X-Pm-Lane: 0
X-Pm-Recipients-Exato: true
Content-Type: application/json
{"id":"0198e7c4-77a1-7bd2-b0f1-6b1d3f2a9c40","recipients":2,"external_id":"cmp-123"}
Repetindo a chamada com a mesma Idempotency-Key e o mesmo corpo, o corpo vem
idêntico e aparece o X-Idempotent-Replay: true — é assim que você distingue,
no seu log, uma segunda campanha de uma repetição segura.
Cabeçalhos nas entregas de webhook
Quando o PushMesh chama o seu endpoint, a requisição sai com:
| Cabeçalho | Conteúdo |
|---|---|
Content-Type | application/json |
X-PM-Evento | delivery.received, delivery.clicked, notification.completed ou teste.ping |
X-PM-Entrega-Id | identificador desta entrega. É a chave de deduplicação do seu lado. |
X-PM-Canal | webhook — por qual canal esta confirmação saiu. O mesmo valor vai dentro do corpo assinado. |
X-PM-Assinatura | sha256=<hex(HMAC-SHA256(segredo, corpo))> |
Detalhes de verificação em Webhooks.
CORS
A API responde com CORS permissivo: qualquer origem, qualquer método,
qualquer cabeçalho, max-age de 3600 segundos — e sem credenciais.
Isso é seguro por construção aqui porque nenhuma rota autentica por cookie:
o SDK se identifica por app_id + teto por IP, a API por chave no cabeçalho, o
painel por token Bearer. Sem autoridade ambiente no navegador não existe CSRF —
o navegador só passa a poder ler o que o curl sempre pôde.
Consequência prática, e ela é séria: a chave pm_live_ nunca deve ir para
código de navegador ou para dentro de um APK/IPA. CORS aberto não é permissão
para expor a chave; é permissão para você experimentar a API a partir de uma
página de documentação. Chamadas autenticadas pertencem ao seu servidor.