> ## 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.

# Chaves de API

> Gerando chaves secretas, publicando as públicas, e a lista de origens que as protege.

Dois tipos de chave, e eles não são intercambiáveis.

## Chaves secretas

`uk_sk_…`, a credencial do seu servidor. Criada no painel, mostrada uma vez,
armazenada como hash SHA-256.

```bash theme={null}
curl -s $API/v1/organization/api-keys \
  -H "Authorization: Bearer $UK_SESSION" \
  -H "X-Organization-Id: org_4b1e…" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "Backend de produção", "environment": "live" }'
```

```json 201 theme={null}
{
  "id": "…",
  "name": "Backend de produção",
  "prefix": "uk_sk_live_a91c",
  "environment": "live",
  "key": "uk_sk_live_a91c…"
}
```

Exige `api_keys:write`.

<Warning>
  `key` é a única vez em que o valor é legível. O que se armazena é o hash, então um
  dump do banco não entrega credencial funcionando — e uma chave perdida é
  substituída, nunca recuperada.
</Warning>

Uma chave nasce dentro de um ambiente e nunca sai dele. O ambiente é escolhido
aqui, gravado no prefixo, e resolvido a partir da linha armazenada em toda
requisição. Nada que quem chama envie depois muda isso.

### Listando

```bash theme={null}
curl -s $API/v1/organization/api-keys \
  -H "Authorization: Bearer $UK_SESSION" \
  -H "X-Organization-Id: org_4b1e…"
```

```json theme={null}
{
  "api_keys": [
    {
      "id": "…",
      "name": "Backend de produção",
      "key_prefix": "uk_sk_live_a91c",
      "environment_kind": "live",
      "last_used_at": "2026-07-29T11:58:00Z",
      "created_at": "…"
    }
  ]
}
```

Exige `api_keys:read`. Só o prefixo de exibição volta — o suficiente para reconhecer
uma chave numa lista, nunca o suficiente para usar uma.

`last_used_at` é carimbado com granularidade de minuto, best-effort: escrever a cada
requisição transformaria um caminho de leitura numa escrita em linha quente.

### Revogando

```bash theme={null}
curl -s -X DELETE $API/v1/organization/api-keys/{id} \
  -H "Authorization: Bearer $UK_SESSION" \
  -H "X-Organization-Id: org_4b1e…"
```

`204`. A linha sobrevive com `revoked_at` carimbado, então o rastro de auditoria de
quais chaves existiram não desaparece com a chave. Chaves revogadas param de
autenticar imediatamente.

### Rotacionando

Não existe endpoint de rotação, porque rotação são duas chamadas e um deploy:

<Steps>
  <Step title="Crie a substituta">
    Mesmo ambiente, um nome que diga por que ela existe.
  </Step>

  <Step title="Faça o deploy">
    As duas chaves funcionam ao mesmo tempo — nada é exclusivo.
  </Step>

  <Step title="Revogue a antiga">
    Confira `last_used_at` antes: se ainda estiver se mexendo, alguma coisa ainda a
    está usando.
  </Step>
</Steps>

## Chaves publicáveis

`uk_pk_…`, uma por ambiente, criada junto com ele. Você nunca cria nem deleta;
você configura.

```bash theme={null}
curl -s $API/v1/organization/publishable-keys \
  -H "Authorization: Bearer $UK_SESSION" \
  -H "X-Organization-Id: org_4b1e…"
```

```json theme={null}
{
  "publishable_keys": [
    {
      "id": "…",
      "key": "uk_pk_live_3d8e…",
      "allowed_origins": ["https://app.example.com"],
      "environment_kind": "live",
      "created_at": "…"
    }
  ]
}
```

Devolvida em **texto puro**, ao contrário de todo segredo: o valor é público por
definição — ele fica no HTML da sua página — e o painel é de onde um desenvolvedor
copia.

Uma chave publicável identifica e quase nada autoriza. Ela abre `/v1/boot` e os
fluxos `/v1/contact-auth/*`, e mais nada.

### A lista de origens permitidas

Essa lista é a fronteira de segurança de verdade de uma chave que é pública por
projeto.

```bash theme={null}
curl -s -X PATCH $API/v1/organization/publishable-keys/{id} \
  -H "Authorization: Bearer $UK_SESSION" \
  -H "X-Organization-Id: org_4b1e…" \
  -H 'Content-Type: application/json' \
  -d '{ "allowed_origins": ["https://app.example.com", "https://example.com"] }'
```

Exige `api_keys:write`.

Entradas são esquema, host e opcionalmente porta. Sem path, sem query, sem
fragmento — um header `Origin` nunca carrega nenhum deles, e uma entrada que
carregasse nunca casaria com nada. Entradas malformadas respondem `400`.

A comparação é **exata** sobre a origem normalizada. Sem curingas, sem prefixos: a
lista é curta, e a ambiguidade de qualquer coisa mais esperta é onde moram os
bypasses.

<Warning>
  Uma **lista vazia permite qualquer origem.** É o estado de começo de vida, para que
  os primeiros dez minutos de ninguém sejam gastos numa tela de CORS. Preencha antes
  de ir para produção.
</Warning>

Com a lista preenchida, uma requisição **sem** header `Origin` também é recusada.
Navegadores sempre mandam um em cross-origin, então "sem Origin" significa "não é um
navegador" — exatamente quem a lista existe para barrar.

Uma origem recusada responde:

```json 403 theme={null}
{
  "error": {
    "code": "origin_not_allowed",
    "message": "this publishable key does not accept calls from this origin"
  }
}
```

### A outra proteção

O boot é limitado por chave publicável — 240 chamadas por minuto — além do limite
por IP. Bots e tráfego de landing page criariam linhas de visitante para sempre, e a
chave é a fronteira de tenant por onde uma enxurrada chega.

## Qual chave vai onde

| Onde                      | Chave     | Por quê                                                |
| ------------------------- | --------- | ------------------------------------------------------ |
| Seu backend, no servidor  | `uk_sk_…` | Acesso completo ao plano de clientes, no ambiente dela |
| Suas páginas web, no HTML | `uk_pk_…` | Pública por projeto, guardada pela lista de origens    |
| Seu app mobile            | `uk_pk_…` | Qualquer coisa embarcada num dispositivo é pública     |
| O painel                  | `uk_st_…` | Uma pessoa, não uma máquina                            |

<Warning>
  Uma chave `uk_sk_` no bundle do navegador é uma chave `uk_sk_` na mão de cada
  visitante. Entregue chaves publicáveis aos clientes; mantenha as secretas nos
  servidores.
</Warning>

## Se uma chave vazar

<Steps>
  <Step title="Revogue">
    `DELETE /v1/organization/api-keys/{id}`. Ela para de funcionar na próxima
    requisição.
  </Step>

  <Step title="Crie a substituta e faça o deploy">
    Mesmo ambiente.
  </Step>

  <Step title="Se era federado, rotacione também o segredo de identidade">
    Um `uk_is_…` vazado é pior que uma chave de API vazada: ele emite sessões
    verificadas para *qualquer* id de usuário. Veja
    [Identidade federada](/pt-br/customer-auth/federated#rotacionando-o-segredo).
  </Step>
</Steps>

Toda credencial carrega um prefixo reconhecível justamente para que uma varredura de
repositório ou um grep de log a encontre antes de outra pessoa.
