> ## Documentation Index
> Fetch the complete documentation index at: https://docs.userkit.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Mensagens e consentimento

> Toda mensagem que esta plataforma envia aos seus usuários declara duas coisas: o que ela diz e quanto ela vale. Uma é decisão de quem recebe, a outra é do seu plano.

Tudo que é enviado a um usuário seu — um link de verificação, um recibo, um
win-back, uma nota de versão — passa por um único funil, e toda mensagem declara
duas coisas ali. Parecem um campo só e não são.

## Duas perguntas, nunca uma

|                  | **Categoria**                                      | **Classe**                                                        |
| ---------------- | -------------------------------------------------- | ----------------------------------------------------------------- |
| Pergunta         | Podemos escrever para esta pessoa sobre isto?      | Quando o ambiente gasta a franquia mensal de e-mails, o que cede? |
| Respondida por   | Quem recebe                                        | O seu plano                                                       |
| Dura             | Até a pessoa mudar                                 | Um mês                                                            |
| Onde você define | No [template da mensagem](/pt-br/guides/campaigns) | Em lugar nenhum — é decidida pelo que a mensagem é                |

Nenhuma é derivável da outra, e é por isso que as duas são declaradas. Um recibo é
**cortesia** e não é marketing: ninguém se descadastra da resposta a algo que fez
com o próprio endereço. Uma campanha é **marketing** e não é de graça: custa um
envio como qualquer outra coisa.

## Três categorias, e transacional não é uma delas

| Categoria      | O que cobre                                                                      |
| -------------- | -------------------------------------------------------------------------------- |
| `marketing`    | O que existe para vender: win-back, empurrão de upgrade, anúncio de algo à venda |
| `product_news` | O que mudou no produto                                                           |
| `surveys`      | Ser perguntado alguma coisa                                                      |

`product_news` é separada de `marketing` de propósito. Quem não quer ofertas ainda
pode querer saber que as ferramentas mudaram, e um interruptor só para as duas
perde essa pessoa inteira. `surveys` é separada porque o custo para quem recebe é
diferente em natureza — um anúncio se lê, um NPS dá trabalho.

**Não existe categoria `transactional`, e nunca vai existir.** Um link de
verificação, uma redefinição de senha, um recibo, uma resposta do suporte e um
aviso de cobrança continuam chegando depois que alguém desliga as três. Isso não é
uma regra aplicada na hora do envio: o valor não existe, então não há linha que uma
tela de preferências, uma atualização em massa ou um erro pudessem escrever para
parar uma dessas.

## A classe ordena mensagens, nunca momentos

Autenticação gratuita só é gratuita se o e-mail por trás dela for, então cada
ambiente tem uma franquia mensal. Estourá-la nunca pode bloquear um login — e uma
mensagem que não sai *é* um cadastro que não se completa, então "nunca bloquear"
também não pode significar "nunca reter". A saída é ordenar as mensagens:

| Classe       | Exemplos                                                          | Além da franquia |
| ------------ | ----------------------------------------------------------------- | ---------------- |
| `security`   | Login de um endereço novo, sessão revogada pelo suporte           | Nunca retida     |
| `credential` | Magic link, código de seis dígitos, admissão numa fila de feature | Nunca retida     |
| `reply`      | Um agente respondendo uma conversa que a pessoa começou           | Nunca retida     |
| `courtesy`   | Boas-vindas, confirmação de fila de feature, uma campanha         | Retida           |

Você não escolhe isso. É o que a mensagem **é**, e campanhas são `courtesy` — uma
campanha retida por orçamento é uma campanha, enquanto um magic link retido por
orçamento é uma autenticação recusada com um passo a mais na frente.

## O consentimento é honrado no envio, em uma instrução só

O registro da entrega e a checagem do consentimento são a mesma escrita. Uma
mensagem que a pessoa desligou nunca é composta, em vez de ser composta e filtrada
depois, e dois envios concorrendo no mesmo contato não conseguem os dois ler "não
se descadastrou" e os dois sair.

Numa campanha a recusa fica visível: o envio é registrado como `suppressed` com o
motivo, que é o que permite ao suporte responder *por que ela não recebeu* com um
fato. Um descadastro que chega entre a reserva do envio e a montagem da mensagem
ainda para o envio — o funil confere de novo.

## O link de descadastro

Toda mensagem não transacional leva o link no rodapé e o par de cabeçalhos
`List-Unsubscribe` / `List-Unsubscribe-Post` no envelope. Nenhuma mensagem
transacional leva qualquer um dos dois: um recibo oferecendo parar de mandar
recibos é uma oferta que este produto não faz.

O link cai numa página hospedada que nomeia o **seu** produto, porque o tenant
viaja no link ao lado do token. Atrás dela:

```http theme={null}
GET  https://api.userkit.dev/v1/unsubscribe/{token}
POST https://api.userkit.dev/v1/unsubscribe/{token}
```

**O `GET` é uma leitura e o `POST` é o ato.** Gateways de e-mail e scanners de
segurança buscam todo link de uma mensagem antes de uma pessoa ver, então um `GET`
que descadastrasse descadastraria quem nunca clicou.

Nenhum dos dois pede credencial de espécie alguma — o token `uk_ns_…` no caminho é
tudo. Isso é o requisito e não uma lacuna: quem lê clicou de uma caixa de entrada
num aparelho onde não está logado, e o descadastro de um clique da RFC 8058 é feito
pelo **cliente de e-mail**, sem navegador nenhum. Um descadastro que primeiro pede
para a pessoa lembrar a senha é um descadastro que falha, e o passo seguinte dela é
o botão de spam.

Pela mesma razão o token **nunca expira e nunca é gasto**. O cliente de e-mail
postando em nome de quem lê e depois a própria pessoa clicando no mesmo link são os
dois chamadores que de fato acontecem, e os dois têm que terminar no mesmo lugar.

Um link desliga **uma categoria de um contato**, e é reversível na mesma página —
`{"opted_out": false}` liga de volta. Ele nunca revela o endereço para o qual foi
enviado: um token vindo de um e-mail encaminhado não pode virar uma consulta de
quem é o dono daquela caixa.

## A tela da própria pessoa

```ts theme={null}
const preferences = await userkit.getNotificationPreferences();

await userkit.updateNotificationPreferences([{ category: "marketing", opted_out: true }]);
```

```json theme={null}
{
  "preferences": [
    { "category": "marketing", "label": "Novidades e ofertas", "opted_out": true },
    { "category": "product_news", "label": "Novidades do produto", "opted_out": false },
    { "category": "surveys", "label": "Pesquisas de satisfação", "opted_out": false }
  ]
}
```

A resposta é sempre o **catálogo inteiro**, não as decisões que por acaso estão
gravadas: a ausência de uma decisão gravada **é** o consentimento, então uma tela
que renderizasse só o que existe seria uma página de preferências vazia para todo
mundo que nunca a abriu. E-mail transacional não aparece na lista, porque não há
nada aqui que pudesse pará-lo.

Uma categoria que esta API não conhece é recusada **pelo nome**, `transactional`
incluída. Uma decisão de consentimento descartada em silêncio é uma tela que diz
*salvo* sobre uma preferência que nunca foi gravada, e a pessoa descobre pelo
próximo e-mail.

Esta é a única parte da autoadministração do contato que **não** exige sessão
verificada. O pior que uma sessão não provada faz aqui é desligar uma categoria do
contato que ela nomeou — exatamente o que o token na caixa de entrada daquele
contato já faz sem sessão nenhuma. Exigir mais prova no controle dentro do produto
do que no do e-mail seria o contrário do certo.

Um descadastro publica um fato internamente e deliberadamente **não** é entregue
como [webhook](/pt-br/guides/webhooks). É o único tipo retido cuja razão é sobre
direção e não sobre permissão: o que qualquer um construiria sobre "esta pessoa se
descadastrou" é uma mensagem do próprio sistema, que é justamente a mensagem que o
fato diz para não mandar.

## O que esta plataforma mandou para uma pessoa

```bash theme={null}
curl "https://api.userkit.dev/v1/organization/contacts/{id}/messages?environment=live" \
  -H "Authorization: Bearer uk_st_…" \
  -H "X-Organization-Id: org_4b1e…"
```

Uma leitura ordenada sobre as três coisas que enviam — campanhas, notificações no
produto e e-mail, transacional incluído — então uma redefinição de senha fica ao
lado do marketing. É protegida por `customers:read` e não por `messaging:manage`:
compor uma campanha e responder *o e-mail de reset chegou?* são trabalhos
diferentes, e o segundo é de quem já pode ver a pessoa.

**Leia `tracked` antes dos quatro carimbos de tempo.** Quando é `false`, nada ia
reportar sobre aquela mensagem — não há webhook de entrega configurado para o
domínio remetente — então `delivered_at`, `opened_at`, `clicked_at` e `bounced_at`
são `null` porque ninguém mediu, e não porque a mensagem falhou. Renderize isso
como *não rastreado*. Quando é `true`, `null` quer dizer *ainda não*.

## Permissões

`messaging:manage` — owner e admin — cobre templates e campanhas, leituras
incluídas: uma mudança de preço ainda não enviada não é algo que uma permissão mais
ampla deva poder ler. O log de entregas acima é `customers:read`, e nada aqui é
limitado por plano exceto **armar** uma campanha.
