C C-Connect Documentação

Enviar pela API

A chamada de envio, campo a campo, com o que cada resposta quer dizer.

Um pedido POST, um JSON, e uma resposta com o identificador da mensagem. A referência completa está em Referência da API; esta página é a explicação.

Autenticação

Uma chave de API em cada pedido, no cabeçalho.

Authorization: Bearer cconnect_xxxxxxxxxxxxxxxxxxxxxxxx

A chave decide de que conta é o pedido, por isso não há nenhum identificador de conta no URL nem no corpo. Se a chave estiver limitada a uma stream, só pode enviar por domínios dessa stream.

O pedido mínimo

curl -X POST https://app.c-connect.pt/v1/messages \
  -H "Authorization: Bearer $CCONNECT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "recibos@mail.empresa.pt",
    "to": "alguem@example.org",
    "subject": "O teu recibo",
    "text": "Obrigado pela tua compra."
  }'

Obrigatórios são o from, o to, e um corpo: text, html, ou os dois.

Os campos

Campo O que é
from Qualquer caixa num domínio teu verificado. Verificamos o domínio, nunca a parte antes do @.
from_name O nome que aparece antes do endereço.
to Um destinatário. Uma mensagem, uma pessoa.
subject O assunto.
text A versão em texto simples.
html A versão em HTML.
headers Cabeçalhos teus, como um objecto.
unsubscribe_url Obrigatório na stream de marketing.
raw Uma mensagem MIME completa que construíste. Ver Enviar MIME em bruto.

Envia sempre text além de html. Um cliente de email que não renderize HTML mostra a alternativa, e uma mensagem só com HTML pontua pior em alguns filtros.

Um destinatário de cada vez

Não há campo para vários destinatários, nem cc, nem bcc. É deliberado:

  • cada mensagem tem o seu estado, os seus eventos e o seu identificador, e uma entrega que falha para um endereço não diz nada sobre os outros;
  • uma supressão é por endereço, e uma mensagem para cinco pessoas das quais uma está suprimida não tem resposta certa;
  • cc numa mensagem automática mostra a cada destinatário o endereço dos outros, o que é uma fuga de dados que ninguém quis.

Para enviar a mil pessoas, faz mil pedidos. A API aguenta.

A resposta

{
  "id": "01JB2XK7Q9R3N8Z6T4V0M5W1YC",
  "message_id_header": "<01JB2XK7Q9R3N8Z6T4V0M5W1YC@c-connect.pt>",
  "status": "queued",
  "stream": "transactional",
  "from": "recibos@mail.empresa.pt",
  "to": "alguem@example.org",
  "subject": "O teu recibo",
  "created_at": "2026-09-18T10:41:02+01:00"
}

O código é 202 Accepted, e não 200. Aceite não é entregue: a mensagem foi assinada e posta em fila, e o que o destino fez com ela chega depois, como eventos. Uma integração que trate 202 como "entregue" vai mentir ao utilizador mais cedo ou mais tarde.

Guarda o id. É por ele que consultas a mensagem, é ele que aparece nos webhooks, e é ele que o suporte pede.

Quando corre mal

Código O que aconteceu O que fazer
401 Chave em falta, desconhecida ou revogada. Verifica o cabeçalho e o painel.
403 A chave está limitada a outra stream. Usa a chave certa para este domínio.
422 O corpo não passou a validação, ou o domínio não é teu, ou não está verificado, ou o endereço está suprimido. Lê o message e os errors.
429 Acima do limite de pedidos. Espera e repete.
5xx Nosso. Repete com espera crescente.

Um 422 por endereço suprimido não é um erro teu: é o sistema a impedir um envio que ia devolver outra vez. Trata-o como um resultado e não como uma falha.

Limites e repetições

Há dois tectos e não um. O limite de pedidos é por chave, 600 por minuto. A quota é da conta inteira, por hora e por dia, e é a que interessa a quem envia em lote: todas as chaves da conta gastam a mesma.

Cada 202 traz o que sobra dela, por isso não precisas de perguntar nem de a descobrir a bater com a cabeça:

X-CConnect-Quota-Window: hour
X-CConnect-Quota-Limit: 2000
X-CConnect-Quota-Remaining: 1873
X-CConnect-Quota-Reset: 1758186000

A janela indicada é a que está mais perto de esgotar, a hora ou o dia, que é a que decide quando podes mandar a próxima. O Reset são segundos desde a época.

Um lote bem escrito lê o Remaining da última resposta e pára quando chega a zero, em vez de continuar a bater no 429. Se quiseres saber o tamanho do lote antes de o começar, GET /v1/me devolve as duas janelas.

A resposta certa a um 429 é esperar o que o Retry-After diz, não abrir mais ligações: mais ligações gastam a mesma quota mais depressa.

Repete um 5xx e um 429. Não repitas um 4xx: o pedido é o mesmo e a resposta vai ser a mesma.

Repetir sem enviar duas vezes

Um 202 que já recebeste e repetes envia uma segunda mensagem. O problema real não é esse, é o outro: um pedido que rebentou a meio, ou uma ligação que caiu depois de nós termos aceitado e antes de tu teres lido a resposta. Nesse caso não sabes se saiu.

Põe uma chave tua no pedido e o problema desaparece:

curl -X POST https://app.c-connect.pt/v1/messages \
  -H "Authorization: Bearer $CCONNECT_KEY" \
  -H "Idempotency-Key: fatura-2026-001" \
  -H "Content-Type: application/json" \
  -d '{ "from": "faturas@mail.empresa.pt", "to": "cliente@exemplo.pt", ... }'

Uma chave por mensagem, escolhida por ti. O identificador que já tens do teu lado costuma ser a melhor: o número da factura, o id da encomenda, o do utilizador mais a acção. Uma chave aleatória por pedido não serve de nada, porque uma repetição gerava outra.

O que acontece a seguir:

Segundo pedido Resposta
Mesma chave, mesmo corpo O mesmo 202 de antes, com Idempotent-Replay: true. Não sai nada.
Mesma chave, corpo diferente 409. A chave já é de outra mensagem.
Mesma chave, o primeiro ainda a correr 409 com Retry-After: 1. Tenta outra vez daqui a um instante.
Sem chave Sai uma segunda mensagem, como sempre saiu.

As chaves são da conta, não da chave de API, e duram 24 horas. Um pedido recusado liberta a chave: se te devolvermos 422 por o endereço estar suprimido, podes corrigir o destinatário e repetir com a mesma.