Sua Carta
Como FuncionaPerguntas FrequentesIntegraçõesAPI Docs

Documentação pública

Dispare cartas manuscritas pelo seu fluxo.

Esta é a visão pública da API da Sua Carta. Agora ela já cobre não só o fluxo comercial, mas também o contrato técnico essencial para um time integrar com menos ida e volta.

Visão geral

Do evento no seu sistema até a carta postada.

A integração foi desenhada para ser direta: um payload entra, um fluxo físico é disparado, e tudo continua rastreável até a entrega.

Fluxo em 4 passos

  1. 1

    Gere sua chave

    Crie a conta, peça o acesso à API e receba a credencial usada em produção ou homologação.

  2. 2

    Envie os dados da carta

    Destino, conteúdo, template, estilo de caligrafia e qualquer identificador que você queira reconciliar no CRM.

  3. 3

    Receba o ID do envio

    A API responde com o identificador da carta, status inicial e previsões para acompanhamento do fluxo físico.

  4. 4

    Atualize sua operação

    Consulte a carta pelo ID ou receba eventos via webhook conforme a produção e a postagem avançam.

O que você manda

Dados do destinatário

Texto da carta ou template aprovado

Estilo de caligrafia

Metadados do seu sistema

O que você recebe

ID único por carta

Status operacional

Estimativa de postagem

Rastreamento quando disponível

Status mais comuns

queuedwritingpostedin_transitdelivered

Autenticação e operação

Tudo o que seu backend precisa antes da primeira chamada.

Produção

https://api.suacarta.com.br/v1

Envio real, rastreamento e status usados pela operação.

Use chaves reais e endereços confirmados.

POSTs devem sempre carregar Idempotency-Key.

Homologação

liberado sob solicitação

Validar payloads, webhooks e rotina antes da primeira campanha.

Pode usar dados de teste e templates controlados.

Combine o fluxo de ativação com o time da Sua Carta.

Headers obrigatórios

Authorization: Bearer sk_live_sua_chave
Content-Type: application/json
Accept: application/json

Idempotência

Envie Idempotency-Key em todo POST /cards e POST /batches.

Reaproveite a mesma chave ao repetir a mesma intenção de negócio.

Monte a chave com um identificador estável, como welcome-{user_id}.

Se a primeira chamada já tiver sido aceita, a repetição devolve o mesmo recurso em vez de criar outra carta.

Rate limits

Os limites variam por conta e podem ser ajustados para operações recorrentes.

As respostas podem trazer X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset.

Ao receber 429, respeite Retry-After e reprograme a chamada com backoff exponencial.

Primeira requisição

Um exemplo direto para colocar a integração de pé.

O fluxo abaixo cria uma carta individual. Ele cobre o caso mais comum: um gatilho no CRM ou no seu back-end dispara o envio, recebe um ID e segue acompanhando o processo por consulta ou webhook.

curl

curl --request POST \
  --url https://api.suacarta.com.br/v1/cards \
  --header 'Authorization: Bearer sk_live_sua_chave' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: welcome-user_92811' \
  --data '{"to":{"name":"Maria Silva","address_line1":"Rua das Flores, 123","address_line2":"Apto 91","city":"São Paulo","state":"SP","zip":"01234-567","country":"BR"},"template":"welcome-premium","style":"elegant","message":"Maria, obrigada por começar com a gente.","schedule_at":"2026-04-18T14:00:00Z","external_id":"user_92811","metadata":{"crm_contact_id":"hs_92811","journey":"onboarding"}}'

Response

{
  "id": "card_82x9a1",
  "external_id": "user_92811",
  "status": "queued",
  "tracking_code": null,
  "tracking_url": null,
  "estimated_posting_at": "2026-04-18T14:00:00Z",
  "created_at": "2026-04-17T19:42:10Z",
  "metadata": {
    "crm_contact_id": "hs_92811",
    "journey": "onboarding"
  }
}

Node.js

const response = await fetch("https://api.suacarta.com.br/v1/cards", {
  method: "POST",
  headers: {
    Authorization: "Bearer sk_live_sua_chave",
    "Content-Type": "application/json",
    "Idempotency-Key": "welcome-user_92811",
  },
  body: JSON.stringify(payload),
});

const card = await response.json();

Python

import requests

response = requests.post(
    "https://api.suacarta.com.br/v1/cards",
    headers={
        "Authorization": "Bearer sk_live_sua_chave",
        "Idempotency-Key": "welcome-user_92811",
    },
    json=payload,
)

card = response.json()

Endpoints

O conjunto essencial para produção, consulta e escala.

POST/cards

Criar uma carta individual

Use para onboarding, pós-venda, prospecção ou qualquer envio unitário disparado pelo seu sistema.

Aceita destinatário, template, estilo e mensagem personalizada.

Retorna o ID da carta para acompanhamento posterior.

Request

{
  "to": {
    "name": "Maria Silva",
    "address_line1": "Rua das Flores, 123",
    "address_line2": "Apto 91",
    "city": "São Paulo",
    "state": "SP",
    "zip": "01234-567",
    "country": "BR"
  },
  "template": "welcome-premium",
  "style": "elegant",
  "message": "Maria, obrigada por começar com a gente.",
  "schedule_at": "2026-04-18T14:00:00Z",
  "external_id": "user_92811",
  "metadata": {
    "crm_contact_id": "hs_92811",
    "journey": "onboarding"
  }
}

Response

{
  "id": "card_82x9a1",
  "external_id": "user_92811",
  "status": "queued",
  "tracking_code": null,
  "tracking_url": null,
  "estimated_posting_at": "2026-04-18T14:00:00Z",
  "created_at": "2026-04-17T19:42:10Z",
  "metadata": {
    "crm_contact_id": "hs_92811",
    "journey": "onboarding"
  }
}
GET/cards/{id}

Consultar status da carta

Busque o estágio atual, o histórico de eventos e o rastreamento assim que ele estiver disponível.

Ideal para telas internas, reconciliação e debug de integrações.

O mesmo ID retornado no POST pode ser usado do começo ao fim do fluxo.

Request

GET /cards/card_82x9a1

Response

{
  "id": "card_82x9a1",
  "external_id": "user_92811",
  "status": "posted",
  "tracking_code": "BR123456789BR",
  "tracking_url": "https://rastreamento.exemplo/BR123456789BR",
  "estimated_posting_at": "2026-04-18T14:00:00Z",
  "created_at": "2026-04-17T19:42:10Z",
  "events": [
    {
      "type": "card.created",
      "at": "2026-04-17T19:42:10Z"
    },
    {
      "type": "card.written",
      "at": "2026-04-18T11:05:00Z"
    },
    {
      "type": "card.shipped",
      "at": "2026-04-18T14:00:00Z"
    }
  ]
}
POST/batches

Enviar cartas em lote

Quando a rotina nasce em planilha, CRM ou campanha recorrente, esse endpoint reduz o custo operacional do disparo.

Cada item do lote mantém seu próprio ID e status.

Bom para campanhas de reativação, cobrança amigável e relacionamento.

Request

{
  "cards": [
    {
      "to": {
        "name": "Cliente 1",
        "address_line1": "Av. Paulista, 1000",
        "city": "São Paulo",
        "state": "SP",
        "zip": "01310-100",
        "country": "BR"
      },
      "template": "reativacao-q2",
      "style": "modern",
      "external_id": "crm_1001"
    }
  ],
  "schedule_at": "2026-04-19T09:00:00Z"
}

Response

{
  "batch_id": "batch_91ad8",
  "status": "queued",
  "total_cards": 1,
  "created_at": "2026-04-17T19:42:10Z"
}
GET/templates

Listar templates aprovados

Veja quais modelos já estão homologados para produção e quais variáveis cada um espera receber.

Ajuda a evitar divergência entre o template aprovado e o payload do sistema.

Útil para produtos com múltiplas jornadas e mensagens por segmento.

Request

GET /templates

Response

{
  "templates": [
    {
      "id": "welcome-premium",
      "name": "Boas-vindas premium",
      "variables": [
        "nome",
        "empresa",
        "plano"
      ]
    },
    {
      "id": "pos-venda-premium",
      "name": "Pós-venda premium",
      "variables": [
        "nome",
        "produto",
        "data_compra"
      ]
    }
  ]
}
GET/styles

Listar estilos de caligrafia

Consulta os estilos liberados para sua operação quando você quiser variar a apresentação da escrita.

Os estilos disponíveis podem variar conforme a configuração da conta.

Use para preencher interfaces internas ou validar preferências antes do envio.

Request

GET /styles

Response

{
  "styles": [
    {
      "id": "elegant",
      "name": "Elegante",
      "description": "Traço refinado e formal."
    },
    {
      "id": "modern",
      "name": "Moderna",
      "description": "Mais limpa e contemporânea."
    }
  ]
}

Contrato

Campos, validação e o envelope de erro que o time espera encontrar.

A integração fica muito mais previsível quando o contrato está explícito. Aqui entram os campos mais importantes do recurso principal, além dos formatos básicos de erro para sua camada de observabilidade.

Campos do POST /cards

Campo

to.name

Tipo

string

Obrigatório

sim

Descrição

Nome completo do destinatário.

Exemplo: Maria Silva

Campo

to.address_line1

Tipo

string

Obrigatório

sim

Descrição

Linha principal do endereço postal.

Exemplo: Rua das Flores, 123

Campo

to.address_line2

Tipo

string

Obrigatório

não

Descrição

Complemento, bloco, apto ou referência.

Exemplo: Apto 91

Campo

to.city

Tipo

string

Obrigatório

sim

Descrição

Cidade de entrega.

Exemplo: São Paulo

Campo

to.state

Tipo

string

Obrigatório

sim

Descrição

UF em duas letras.

Exemplo: SP

Campo

to.zip

Tipo

string

Obrigatório

sim

Descrição

CEP do destinatário.

Exemplo: 01234-567

Campo

to.country

Tipo

string

Obrigatório

não

Descrição

País ISO-2. Quando omitido, o padrão é BR.

Exemplo: BR

Campo

template

Tipo

string

Obrigatório

condicional

Descrição

ID de um template aprovado na sua conta.

Exemplo: welcome-premium

Campo

message

Tipo

string

Obrigatório

condicional

Descrição

Texto livre da carta. Use quando não estiver chamando um template pronto.

Exemplo: Maria, obrigada por começar com a gente.

Campo

style

Tipo

string

Obrigatório

não

Descrição

Estilo de caligrafia a usar na produção.

Exemplo: elegant

Campo

schedule_at

Tipo

datetime

Obrigatório

não

Descrição

Agenda a carta para ser liberada em um instante futuro.

Exemplo: 2026-04-18T14:00:00Z

Campo

external_id

Tipo

string

Obrigatório

não

Descrição

ID do seu sistema para conciliação e troubleshooting.

Exemplo: user_92811

Campo

metadata

Tipo

object

Obrigatório

não

Descrição

Chaves livres para guardar contexto de negócio e receber de volta nos webhooks.

Exemplo: {"journey":"onboarding"}

Campos retornados em /cards/{id}

Campo

id

Tipo

string

Obrigatório

sempre

Descrição

Identificador único da carta dentro da Sua Carta.

Exemplo: card_82x9a1

Campo

external_id

Tipo

string | null

Obrigatório

quando enviado

Descrição

Espelho do external_id enviado por você.

Exemplo: user_92811

Campo

status

Tipo

enum

Obrigatório

sempre

Descrição

Estado atual da carta: queued, writing, posted, in_transit ou delivered.

Exemplo: queued

Campo

tracking_code

Tipo

string | null

Obrigatório

quando disponível

Descrição

Código de rastreamento após postagem.

Exemplo: BR123456789BR

Campo

tracking_url

Tipo

string | null

Obrigatório

quando disponível

Descrição

Link amigável de rastreamento.

Exemplo: https://rastreamento.exemplo/BR123456789BR

Campo

estimated_posting_at

Tipo

datetime | null

Obrigatório

quando calculado

Descrição

Previsão operacional para postagem.

Exemplo: 2026-04-18T14:00:00Z

Campo

created_at

Tipo

datetime

Obrigatório

sempre

Descrição

Momento em que a carta foi aceita pela API.

Exemplo: 2026-04-17T19:42:10Z

Campo

events[]

Tipo

array

Obrigatório

na consulta detalhada

Descrição

Linha do tempo da carta com eventos operacionais.

Exemplo: [{"type":"card.shipped"}]

Campo

metadata

Tipo

object

Obrigatório

quando enviada

Descrição

Metadados devolvidos sem alteração para reconciliação.

Exemplo: {"crm_contact_id":"hs_92811"}

Erro 422

{
  "error": {
    "type": "validation_error",
    "code": "invalid_zip",
    "message": "CEP inválido para o endereço informado.",
    "request_id": "req_8m5n21"
  }
}

Erro 401

{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "A API key enviada não é válida.",
    "request_id": "req_0n9sx1"
  }
}

Webhooks

Atualize seu sistema por evento, com verificação e retry seguro.

Se a operação já é orientada por eventos, a recomendação é receber cada mudança de status no seu endpoint e validar a assinatura antes de processar o payload.

card.created

Recebemos a carta e ela entrou na fila operacional.

card.written

A etapa de escrita foi concluída e a carta está pronta para postagem.

card.shipped

A carta foi postada e já pode carregar código de rastreamento.

card.delivered

O fluxo físico terminou com entrega confirmada.

card.returned

Houve devolução por problema de endereço ou ausência do destinatário.

Headers de verificação

Header

X-SuaCarta-Signature

Obrigatório

sim

Descrição

Assinatura HMAC SHA-256 do corpo bruto da requisição.

Header

X-SuaCarta-Timestamp

Obrigatório

sim

Descrição

Unix timestamp usado na composição da assinatura e na proteção contra replay.

Header

X-SuaCarta-Event

Obrigatório

sim

Descrição

Nome do evento disparado, útil para roteamento rápido antes do parse completo.

Payload de exemplo

{
  "event": "card.shipped",
  "data": {
    "id": "card_82x9a1",
    "external_id": "user_92811",
    "status": "posted",
    "created_at": "2026-04-17T19:42:10Z",
    "tracking_code": "BR123456789BR",
    "tracking_url": "https://rastreamento.exemplo/BR123456789BR",
    "metadata": {
      "crm_contact_id": "hs_92811"
    }
  },
  "occurred_at": "2026-04-18T14:00:00Z"
}

Node.js: verificar assinatura

import crypto from "node:crypto";

function verifyWebhook({ payload, timestamp, signature, secret }) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${payload}`)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature, "hex"),
    Buffer.from(expected, "hex")
  );
}

Segurança e retries

Monte a assinatura com HMAC SHA-256 sobre timestamp.payload usando o secret do webhook.

Valide a janela do timestamp para evitar replays de payload antigo.

Responda 2xx apenas depois de persistir o evento ou enfileirá-lo internamente.

Se o seu endpoint falhar, a recomendação é reenfileirar com retries exponenciais por até 24 horas.

Playbook pronto

Exemplo real: disparar carta para novos usuários.

Este é o fluxo que mais ajuda um desenvolvedor a sair do conceito e ir para a implementação de verdade. Ele combina gatilho, idempotência, persistência do retorno e consumo posterior dos webhooks.

Fluxo sugerido

1

Escolha o gatilho

Dispare a integração quando o usuário atingir o momento certo: conta criada, pagamento aprovado ou onboarding concluído.

2

Valide endereço e consentimento

Antes de chamar a API, confirme que o usuário tem endereço postal completo e pode receber comunicação física.

3

Crie a carta com idempotência

Use uma Idempotency-Key derivada do usuário, como welcome-{user_id}, para impedir duplicidade em retries.

4

Persista o retorno

Guarde card.id, status e external_id no seu banco para conciliar webhooks, suporte e analytics.

5

Atualize a jornada

Ao receber webhooks, sincronize o status no CRM, timeline do usuário ou painel interno.

Node.js: sendWelcomeLetter

export async function sendWelcomeLetter(user) {
  if (!user.postalAddress) return;

  const payload = {
    to: {
      name: user.name,
      address_line1: user.postalAddress.line1,
      city: user.postalAddress.city,
      state: user.postalAddress.state,
      zip: user.postalAddress.zip,
      country: "BR",
    },
    template: "welcome-premium",
    external_id: user.id,
    metadata: {
      user_id: user.id,
      journey: "new-user",
    },
  };

  const response = await fetch("https://api.suacarta.com.br/v1/cards", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SUACARTA_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": `welcome-${user.id}`,
    },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    throw new Error("Falha ao criar carta de boas-vindas.");
  }

  const card = await response.json();

  await db.user_touchpoints.create({
    data: {
      userId: user.id,
      channel: "handwritten_letter",
      externalId: card.id,
      status: card.status,
    },
  });
}

Checklist de produção

Autenticação isolada no backend: Nunca exponha a API key da Sua Carta no front-end ou em código cliente.

Idempotência em todos os POSTs: Evite carta duplicada quando houver retry de rede ou reprocessamento de jobs.

Persistência do card.id: Sem isso, fica difícil correlacionar webhooks, rastreio e suporte operacional.

Verificação de assinatura dos webhooks: Assine e valide o payload bruto para evitar spoofing de eventos.

Logs com request_id: Inclua request_id e external_id nos logs para investigar falhas com rapidez.

Fallback para erros 429 e 5xx: Use backoff exponencial e fila de retry para não perder o gatilho da carta.

Erros e suporte

Códigos operacionais que seu cliente HTTP deve tratar bem.

HTTP

400

Código

invalid_request

Quando acontece

JSON malformado ou combinação inválida de campos.

Como reagir

Corrija o payload antes de repetir a chamada.

HTTP

401

Código

invalid_api_key

Quando acontece

Bearer token ausente, inválido ou revogado.

Como reagir

Revise a chave configurada no servidor.

HTTP

404

Código

card_not_found

Quando acontece

O ID consultado não existe ou não pertence à conta.

Como reagir

Confira o ID persistido e o ambiente usado.

HTTP

409

Código

idempotency_conflict

Quando acontece

A mesma Idempotency-Key foi reaproveitada com payload diferente.

Como reagir

Mantenha a chave estável apenas para a mesma intenção de negócio.

HTTP

422

Código

invalid_zip

Quando acontece

Dados passaram pelo parser, mas falharam na validação de negócio.

Como reagir

Revise endereço, template e campos obrigatórios.

HTTP

429

Código

rate_limit_exceeded

Quando acontece

A conta ultrapassou o limite temporário de requisições.

Como reagir

Use Retry-After e retente com backoff exponencial.

HTTP

500

Código

internal_error

Quando acontece

Falha inesperada no processamento da solicitação.

Como reagir

Registre request_id, faça retry seguro e acione o suporte se persistir.

Próximo passo

Leve a carta para o seu stack com contrato, exemplos e checklist.

O fluxo público, a spec OpenAPI e a área interna agora cobrem autenticação, schemas, erros, webhooks e um playbook pronto de onboarding.