# API do Claritio — documentação

> Documentação completa da API de integração do Claritio (sistema de RH).
> Gerada de `docs-site/conteudo.mjs`. Versão da API: v1.
> Endereço: https://rh.claritio.com.br/api/publica/v1
> Chave do simulador (pública, dados de mentira): clr_demo_0000000000000000000000000000

## Visão geral

A API do Claritio deixa o seu sistema ler e lançar dados de RH: quem trabalha
na empresa, o ponto que essas pessoas bateram, as ocorrências do período e o
espelho de cada mês.

Ela é **HTTP com JSON**, autenticada por uma chave que a empresa gera dentro do
sistema. Não há SDK a instalar, não há OAuth, não há sessão: um cabeçalho e
pronto.

**O endereço de tudo:**

```
https://rh.claritio.com.br/api/publica/v1
```

O `/v1` faz parte do endereço de propósito. No dia em que um campo precisar
mudar de forma, sai um `/v2` e o `/v1` continua respondendo — a sua
integração não quebra porque nós evoluímos.

## Começar em 3 minutos

Não precisa de cadastro, nem de chave, nem de falar com ninguém para ver a API
funcionando. Escolha a sua linguagem e cole:

**curl**

```bash
curl -H "Authorization: Bearer clr_demo_0000000000000000000000000000" \
  "https://rh.claritio.com.br/api/publica/v1/ping"
```

**PowerShell**

```powershell
$cabecalho = @{ Authorization = "Bearer clr_demo_0000000000000000000000000000" }

# O ConvertTo-Json no fim nao e enfeite: sem ele, a tabela padrao do
# PowerShell mostra os objetos de dentro como "empresa=", em branco, e
# parece que a resposta veio vazia.
Invoke-RestMethod -Uri "https://rh.claritio.com.br/api/publica/v1/ping" -Headers $cabecalho |
  ConvertTo-Json -Depth 5
```

**JavaScript**

```javascript
const r = await fetch("https://rh.claritio.com.br/api/publica/v1/ping", {
  headers: { Authorization: "Bearer clr_demo_0000000000000000000000000000" }
});
console.log(await r.json());
```

**Python**

```python
import requests

r = requests.get("https://rh.claritio.com.br/api/publica/v1/ping",
                 headers={"Authorization": "Bearer clr_demo_0000000000000000000000000000"})
print(r.json())
```

Essa é a **chave do simulador** — pública, e de propósito. Ela responde dados
de uma empresa que não existe e não grava nada. Serve para você escrever e
testar o seu cliente inteiro antes de pedir uma chave de verdade ao seu
cliente.

Quando estiver pronto, troque a chave e o mesmo código passa a falar com os
dados reais. Nada mais muda.

No **Windows**, use a aba do PowerShell: lá o `curl` é apelido de
`Invoke-WebRequest`, que não entende `-H` nem a barra de quebra de linha —
o exemplo de curl colado no PowerShell dá um erro que não fala de HTTP.

E termine sempre com `| ConvertTo-Json -Depth 5`: a tabela padrão do
PowerShell mostra os objetos aninhados como `empresa=`, em branco, e dá a
impressão de que a resposta veio vazia quando ela veio inteira.

## Autenticação

Toda chamada leva a chave num cabeçalho:

```
Authorization: Bearer clr_xxxxxxxxxxxxxxxxxxxxxxxx
```

Se for mais fácil no seu cliente, `X-Api-Key: clr_...` funciona igual.

**Como a empresa gera a chave:** dentro do sistema, em
*Configurações → Integrações → API de integração*. A chave aparece **uma vez**,
na hora em que é criada — o Claritio guarda só um resumo criptográfico dela, do
mesmo jeito que uma senha. Perdeu, é só criar outra e revogar a antiga.

**Guarde a chave como senha.** Ela dá acesso ao cadastro de pessoas da empresa.
Não a coloque no código do aplicativo, no repositório nem no navegador de
ninguém: ela é para o seu servidor.

## Escopos

Cada chave carrega só o que precisa. Quem cria escolhe:

| Escopo | O que libera |
|---|---|
| `pessoas:ler` | Lista de colaboradores, **com CPF** |
| `pessoas:escrever` | Cadastrar, corrigir e desligar |
| `ponto:ler` | Batidas e espelho |
| `ponto:escrever` | Lançar batidas |
| `ocorrencias:ler` | Faltas, atrasos e atestados |
| `ponto:fotos` | O endereço da foto tirada na batida |

Chamar uma rota sem o escopo dela responde **403** dizendo qual escopo falta e
quais a chave tem. Se a sua integração só monta relatório, peça uma chave sem
`ponto:escrever` — ela não vai poder estragar nada nem por engano.

**`pessoas:escrever` dá mais poder do que parece.** O CPF é o login do
Portal do Colaborador: quem tem este escopo decide quem consegue bater ponto.
Não peça se a sua integração só lê.

**`ponto:fotos` é separado de propósito.** Uma batida é hora e lugar; a foto é
o rosto de uma pessoa. São riscos de tamanhos diferentes, e por isso são
interruptores diferentes: quem só concilia jornada não precisa receber
biometria junto.

## Erros

Resposta boa é sempre assim:

```json
{ "ok": true, "total": 28, "inicio": 0, "limite": 100, "dados": [ … ] }
```

Erro é assim:

```json
{ "ok": false, "error": "esta chave não tem o escopo \"ponto:escrever\"." }
```

| Código | O que houve |
|---|---|
| **400** | Falta um parâmetro, ou ele veio num formato que não dá para ler |
| **401** | Chave ausente, inválida ou revogada |
| **403** | Falta o escopo, ou a empresa não tem a API no plano |
| **404** | A matrícula ou o id que você mandou não existe nesta empresa |
| **429** | Passou do limite de chamadas por minuto |
| **5xx** | Foi problema nosso — tente de novo com espera crescente |

As mensagens de erro são escritas para serem lidas por gente. Mostre a
`error` no seu log: ela quase sempre diz exatamente o que corrigir.

## Limites

São dois tetos, e eles protegem coisas diferentes.

| Teto | Padrão | O que ele protege |
|---|---|---|
| Por minuto | **120** | O servidor, de picos |
| Por dia | **20.000** | O dado, de uma chave que vazou ou de um laço maluco |

Os dois sobem sob pedido quando a integração justificar. Toda resposta traz os
quatro cabeçalhos:

```
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 47
X-RateLimit-Day-Limit: 20000
X-RateLimit-Day-Remaining: 19874
```

Estourou, vem **429** com `Retry-After` em segundos. Espere o que ele diz, em
vez de tentar de novo na hora. O teto do dia zera à meia-noite de Brasília.

**Por que um teto diário:** 120 por minuto são 172 mil chamadas por dia, e cada
uma pode levar 500 batidas. O teto por minuto nunca seria atingido por uma
integração mal escrita que reconsulta o mês inteiro a cada volta de um laço — e
é justamente esse tipo de acesso que ninguém quer descobrir só na conta do mês.

**Peça o teto certo, não o maior.** Uma sincronização diária de 500 pessoas com
90 dias de ponto cabe em menos de 100 chamadas. Teto apertado é o que faz uma
chave roubada parar sozinha.

O **simulador** tem limite próprio e menor (60/min no total, somando todo
mundo): ele é público e não tem dono.

## Segurança

**A chave é do seu servidor.** Não a coloque no aplicativo, no repositório nem
em código que roda no navegador de alguém. Quem tem a chave lê o cadastro de
pessoas da empresa inteira.

**Trave a chave nos seus IPs.** Ao criar, a empresa pode listar os endereços do
seu servidor — aceita IP exato, e faixa `200.1.2.0/24` em IPv4. Com a lista
preenchida, a chave **só funciona de lá**: se o arquivo de configuração vazar,
ela não serve em outra máquina. É a trava mais barata e a mais eficaz.

(IPv6 casa por endereço exato, não por faixa. Preferimos dizer isso a prometer
o que não fazemos.)

**Peça só os escopos que usa.** Uma chave de relatório com `ponto:escrever`
pode lançar batida por engano de código — e batida lançada mexe na jornada de
uma pessoa de verdade.

**Revogar é imediato.** A validade é conferida a cada chamada: revogou, a
próxima já responde 401. Não há cache para esperar.

**O que o Claritio registra:** quando a chave foi usada pela última vez e
quantas chamadas ela fez, no dia e no total. Isso aparece na tela de quem
contratou — é como a empresa descobre a chave esquecida que ninguém usa mais,
ou a que passou a usar dez vezes mais que o normal.

**Dados de colaborador são dados pessoais.** O que sai daqui é regido pela
LGPD tanto no seu lado quanto no nosso: guarde só o que for usar, pelo tempo em
que for usar.

## Datas, fusos e páginas

**Datas** são `AAAA-MM-DD`. **Horários** vão e voltam em ISO 8601 com fuso:
`2026-09-26T08:03:00-03:00`.

O dia de uma batida é o dia em **Brasília**, que é o fuso em que a jornada é
apurada. Uma batida às 22h de terça é de terça, mesmo que em UTC já seja
quarta. Mandar o horário com fuso é o que garante isso — evite mandar sem.

**Na resposta, o deslocamento pode vir como `+00:00`** em vez de `-03:00`:
é o mesmo instante escrito de outro jeito. Converta com a biblioteca de datas
da sua linguagem em vez de recortar o texto — e use sempre o campo `dia` para
saber a que jornada a batida pertence, que é o que o RH enxerga.

**Páginas:** as listas aceitam `limite` (padrão 100, teto 500) e `inicio`
(padrão 0), e devolvem `total`. Para varrer tudo, vá somando `inicio` até
passar do `total`.

## Simulador

A chave abaixo é pública e pode ficar no seu README:

```
clr_demo_0000000000000000000000000000
```

Com ela, **todas** as rotas respondem dados de exemplo de uma padaria que não
existe. As conferências são as mesmas da API de verdade: data em formato
errado dá 400 igual, matrícula que não existe dá 404 igual, e o POST de batidas
responde `repetida` quando você reenvia o mesmo `id_externo` — sem gravar
nada em lugar nenhum.

Os nomes e as matrículas são estáveis entre chamadas (para você comparar duas
execuções), e as datas acompanham o dia de hoje (para o exemplo não envelhecer).

As quatro pessoas do simulador:

| Matrícula | Nome | Setor | Situação |
|---|---|---|---|
| `000101` | Ana Paula Ribeiro | Produção | ativa |
| `000102` | Bruno Carvalho Lima | Atendimento | ativa |
| `000103` | Carla Souza Nunes | Administrativo | ativa |
| `000104` | Diego Martins Alves | Produção | desligado |

## GET /ping

`GET https://rh.claritio.com.br/api/publica/v1/ping` — sem escopo

Diz se a chave funciona, de que empresa ela é e o que ela pode fazer. É a
primeira chamada de quem está configurando — e a que você deve usar num
healthcheck.

Não exige escopo nenhum: basta a chave estar viva.

```json
{
  "ok": true,
  "dados": {
    "empresa": { "id": "…", "nome": "PADARIA AURORA LTDA", "cnpj": "…" },
    "chave": { "nome": "ERP da contabilidade",
               "escopos": ["pessoas:ler", "ponto:ler"],
               "limite_por_minuto": 120 },
    "versao": "v1"
  }
}
```

## GET /colaboradores

`GET https://rh.claritio.com.br/api/publica/v1/colaboradores` — escopo `pessoas:ler`

Quem trabalha na empresa.

| Parâmetro | Padrão | O que faz |
|---|---|---|
| `situacao` | `ativos` | `ativos`, `desligados` ou `todos` |
| `desde` | — | Só quem mudou a partir desta data/hora ISO |
| `limite` | 100 | Até 500 |
| `inicio` | 0 | Para paginar |

O **CPF vem na lista** porque é ele que identifica a pessoa no seu sistema —
e porque sem ele a sua tela de edição abriria com o campo vazio, dando a
entender que o cadastro está sem CPF. Trate-o como dado pessoal: ele é o login
do portal.

**Use o `desde`.** Numa sincronização diária, ele é a diferença entre puxar
quatro mil cadastros toda noite e puxar os três que mudaram.

```json
{
  "ok": true, "total": 3, "inicio": 0, "limite": 100,
  "dados": [
    { "id": "…", "nome": "Ana Paula Ribeiro", "matricula": "000101",
      "cpf": "52998224725", "telefone": "11999998888",
      "email": "ana.ribeiro@exemplo.com.br", "setor": "Produção",
      "cargo": "Padeira", "admitido_em": "2023-03-06",
      "desligado_em": null, "tipo": "clt",
      "atualizado_em": "2026-09-24T09:14:22-03:00" }
  ]
}
```

## POST /colaboradores

`POST https://rh.claritio.com.br/api/publica/v1/colaboradores` — escopo `pessoas:escrever`

Cadastra uma pessoa. **Nome e CPF são o mínimo** — o resto é opcional.

```json
{ "nome": "João da Silva", "cpf": "529.982.247-25" }
```

| Campo | Obrigatório | Observação |
|---|---|---|
| `nome` | sim | |
| `cpf` | sim | Com ou sem pontuação. Os dígitos são conferidos |
| `matricula` | não | O seu número para essa pessoa |
| `cargo` / `setor` | não | Texto livre |
| `email` | não | Para onde vai o comprovante de ponto, se a empresa usar |
| `telefone` | não | Só dígitos |
| `admitido_em` | não | `AAAA-MM-DD` |

**O CPF é o login.** É com ele que a pessoa entra no Portal do Colaborador
para bater ponto — não é um campo de cadastro qualquer. Por isso o dígito
verificador é conferido aqui: um número trocado criaria alguém que nunca
consegue entrar, e a tela diria só "CPF não encontrado".

**CPF repetido responde quem já é dono dele** (409), com o id — assim a sua
integração pode usar o cadastro que já existe em vez de travar.

### O que esta rota não faz

Não cria escala, turno nem salário. Uma pessoa sem escala **bate ponto
normalmente e tem a localização gravada**; o que ela não tem é jornada
esperada — então o sistema não lança falta nem atraso, e o banco de horas
fica em zero.

Para muita integração isso é o certo: inventar uma jornada de 8h para quem
trabalha em obra faria o sistema acusar falta de quem estava trabalhando.
Quem precisa de apuração cadastra o turno pelo sistema, que é onde essa
decisão pertence.

## POST /colaboradores/atualizar

`POST https://rh.claritio.com.br/api/publica/v1/colaboradores/atualizar` — escopo `pessoas:escrever`

Corrige o cadastro, ou desliga.

```json
{ "colaborador": "000101", "cargo": "Pintor", "telefone": "11999998888" }
```

`colaborador` aceita o id ou a matrícula. **Campo que não vem não é
tocado**; mandar `null` apaga o valor.

`desligado_em` com uma data desliga a pessoa — e ela perde o acesso ao
portal no mesmo instante, porque o login confere isso a cada entrada. Com
`null`, reativa.

Trocar o CPF troca o login. Se o novo já for de outra pessoa da mesma
empresa, a resposta é **409** dizendo de quem é.

## GET /batidas

`GET https://rh.claritio.com.br/api/publica/v1/batidas` — escopo `ponto:ler`

As batidas de um período.

A batida sai **inteira**: hora, lugar, aparelho, se foi negada, se alguém
mexeu nela e o que ela era antes. É o registro que sustenta uma contestação
trabalhista — um campo que faltasse aqui seria uma resposta que o seu cliente
não conseguiria dar.

| Parâmetro | Obrigatório | O que faz |
|---|---|---|
| `de` | sim | Primeiro dia (`AAAA-MM-DD`) |
| `ate` | sim | Último dia — no máximo 92 dias depois do `de` |
| `colaborador` | não | Matrícula ou id. Sem ele, vêm todos |
| `negadas` | não | `sim` inclui as batidas recusadas |
| `foto` | não | `sim` acrescenta a foto (exige `ponto:fotos`) |
| `limite` / `inicio` | não | Paginação (até 500 por página) |

**Os três recortes que você provavelmente quer:**

```
/batidas?de=2026-09-26&ate=2026-09-26                 → o dia de hoje, todo mundo
/batidas?de=2026-09-01&ate=2026-09-30                 → o mês inteiro, todo mundo
/batidas?de=2026-09-01&ate=2026-09-30&colaborador=000101   → o mês de uma pessoa
```

O teto de 92 dias existe porque a primeira chamada de todo integrador pede
cinco anos, e a resposta não caberia na memória — nem na dele. Para carregar
histórico, vá trimestre a trimestre.

### O que vem em cada batida

| Campo | O que é |
|---|---|
| `id` | O identificador dela aqui |
| `colaborador` | O id de quem bateu |
| `dia` | O dia da jornada (Brasília), que pode diferir da data do horário |
| `quando` | O instante, com fuso |
| `tipo` | `entry`, `break_start`, `break_end`, `exit`, `extra` |
| `origem` | `totem`, `portal_celular`, `portal_celular_offline`, `api`, `manual`… |
| `conferencia` | Como a pessoa se identificou: `facial`, `qrcode`, `geolocalizacao`… |
| `aparelho` | O totem que registrou, quando foi num totem |
| `origem_da_hora` | `server` (nosso relógio) ou `device_clock`/`elapsed` (bateu sem rede) |
| `recebida_em` | Quando chegou até nós — só difere em batida feita offline |
| `ip_de_origem` | De onde veio a chamada, quando pelo celular |
| `id_externo` | O seu número, quando a batida veio pela API |
| `local` | `{ lat, lng, precisao_m }` ou `null` |
| `situacao` | `valida`, `em_analise` ou `negada` |
| `negada_em` / `motivo_da_negativa` | Quando e por que foi recusada |
| `observacao` | O que o sistema anotou (fora do perímetro, sem foto…) |
| `lancada_a_mao` / `motivo_do_lancamento` | Se foi digitada, e por quê |
| `alterada_em` / `alterada_por` | Quando alguém corrigiu, e quem |
| `hora_original` | O horário **antes** da correção. `null` se nunca mudou |
| `rostos_na_foto` | Quantos rostos a foto tinha (mais de um merece um olhar) |
| `semelhanca_do_rosto` / `prova_de_vida` | O que o reconhecimento facial apurou |
| `foto` | Endereço temporário da foto — só com `foto=sim` e `ponto:fotos` |
| `anexo` | Documento anexado à batida, quando houver |
| `minutos_trabalhados` / `minutos_no_banco` | O que o fechamento gravou |
| `evento_do_sistema` | Preenchido quando a linha é lançamento do sistema, não batida |
| `atestado` | O id do documento, quando a linha veio de um |

**Negadas ficam de fora por padrão.** Batida negada não conta jornada;
entregá-la misturada com as boas faria qualquer soma sua sair errada sem você
ter como saber. Quem está auditando pede `negadas=sim`.

**A foto tem duas travas:** o escopo `ponto:fotos` na chave **e** o
`foto=sim` no pedido. O endereço que volta vale **uma hora** — é para abrir e
conferir, não para guardar no seu banco. Se você precisa arquivar, baixe o
arquivo; o endereço vence.

## POST /batidas

`POST https://rh.claritio.com.br/api/publica/v1/batidas` — escopo `ponto:escrever`

Lança batidas vindas de outro relógio ou sistema. Até **200 por chamada**.

```json
{
  "batidas": [
    { "colaborador": "000101",
      "quando": "2026-09-26T08:03:00-03:00",
      "id_externo": "REL-88213" }
  ]
}
```

**`colaborador`** aceita a matrícula ou o id — use a matrícula, que é o que o
seu sistema já conhece.

**`id_externo` é o seu número para aquela batida.** Mande sempre. É ele que
faz o reenvio ser seguro: se a conexão cair depois de gravarmos, você tenta de
novo e a resposta vem marcada `"repetida": true`, sem criar uma segunda
batida. Sem ele, o reenvio duplica — e o estrago não é uma linha repetida, é o
tipo de todas as batidas seguintes andando uma casa.

Aceita qualquer texto: `"REL-88213"`, `"1042"`, um UUID. Só precisa ser
único para aquela batida, no seu sistema.

**A resposta é por item, e o HTTP é 200 mesmo com falhas:**

```json
{
  "ok": true, "gravadas": 1, "repetidas": 0, "falhas": 1,
  "dados": [
    { "indice": 0, "ok": true, "repetida": false, "id": "…",
      "colaborador": "…", "dia": "2026-09-26", "tipo": "entry" },
    { "indice": 1, "ok": false, "erro": "não achei a matrícula \"9999\"" }
  ]
}
```

Olhe `falhas` e o `erro` de cada item — não só o código HTTP. Um lote com
199 sucessos e 1 erro é um 200.

**O tipo você não manda.** Ele é calculado pela posição da batida no dia, e
reordenado depois de cada importação: pode mandar o dia inteiro fora de ordem
que `entry`, `break_start`, `break_end` e `exit` saem certos no fim.

Batida com mais de 30 minutos no futuro é recusada.

**curl**

```bash
curl -X POST "https://rh.claritio.com.br/api/publica/v1/batidas" \
  -H "Authorization: Bearer $CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"batidas":[{"colaborador":"000101","quando":"2026-09-26T08:03:00-03:00","id_externo":"REL-88213"}]}'
```

**PowerShell**

```powershell
$corpo = @{ batidas = @(
    @{ colaborador = "000101"
       quando      = "2026-09-26T08:03:00-03:00"
       id_externo  = "REL-88213" }
) } | ConvertTo-Json -Depth 5

Invoke-RestMethod -Method Post -Uri "https://rh.claritio.com.br/api/publica/v1/batidas" `
  -Headers @{ Authorization = "Bearer $CHAVE" } `
  -ContentType "application/json" -Body $corpo
```

**JavaScript**

```javascript
const r = await fetch("https://rh.claritio.com.br/api/publica/v1/batidas", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${CHAVE}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ batidas: [
    { colaborador: "000101",
      quando: "2026-09-26T08:03:00-03:00",
      id_externo: "REL-88213" }
  ]})
});
const { dados } = await r.json();
```

## GET /ocorrencias

`GET https://rh.claritio.com.br/api/publica/v1/ocorrencias` — escopo `ocorrencias:ler`

Faltas, atrasos e atestados do período, com o que cada um mexeu no banco de
horas.

| Parâmetro | Obrigatório | O que faz |
|---|---|---|
| `de` / `ate` | sim | O intervalo (`AAAA-MM-DD`) |
| `colaborador` | não | Matrícula ou id |
| `canceladas` | não | `sim` inclui as canceladas |

`minutos_banco` é o número que a folha usa: negativo desconta. Canceladas
ficam de fora por padrão — elas existem para auditoria, e quem soma uma lista
que as inclui soma o que foi desfeito.

`pontos` é o desconto na nota de desempenho, quando a empresa usa esse
controle.

## GET /espelho

`GET https://rh.claritio.com.br/api/publica/v1/espelho` — escopo `ponto:ler`

O espelho de ponto de uma pessoa num mês: cada dia com as batidas e o que
entrou ou saiu do banco de horas.

| Parâmetro | Obrigatório | O que faz |
|---|---|---|
| `mes` | sim | `AAAA-MM` |
| `colaborador` | sim | Matrícula ou id |

O colaborador é obrigatório de propósito: a empresa inteira num mês são
milhares de dias, e uma resposta que não dá para paginar é a que derruba o
servidor de quem pediu.

```json
{
  "ok": true,
  "colaborador": { "id": "…", "nome": "Ana Paula Ribeiro", "matricula": "000101" },
  "mes": "2026-09",
  "saldo_do_mes_em_minutos": -18,
  "dados": [
    { "dia": "2026-09-01",
      "batidas": [ { "quando": "2026-09-01T08:00:00-03:00", "tipo": "entry" } ],
      "minutos_banco": 0, "lancamentos": [] }
  ]
}
```

## Receitas

**Sincronizar o cadastro toda noite**

```js
const desde = ultimaSincronizacao.toISOString();
const r = await fetch(`${BASE}/colaboradores?situacao=todos&desde=${desde}&limite=500`,
                      { headers: { Authorization: `Bearer ${CHAVE}` } });
const { dados } = await r.json();
for (const pessoa of dados) gravarNoMeuSistema(pessoa);
```

**Mandar as batidas do relógio, em lote**

```js
const lote = batidasPendentes.slice(0, 200).map(b => ({
    colaborador: b.matricula,
    quando: b.horario.toISOString(),
    id_externo: String(b.id),          // o SEU id, para o reenvio ser seguro
}));

const r = await fetch(`${BASE}/batidas`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${CHAVE}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ batidas: lote }),
});
const { dados } = await r.json();

// Sucesso E repetida saem da fila: repetida quer dizer "já está lá".
for (const item of dados) {
    if (item.ok) marcarComoEnviada(lote[item.indice]);
    else registrarErro(lote[item.indice], item.erro);
}
```

**Fechar o mês de uma pessoa**

```bash
curl -H "Authorization: Bearer $CHAVE" \
  "https://rh.claritio.com.br/api/publica/v1/espelho?mes=2026-09&colaborador=000101"
```

## Perguntas frequentes

**Preciso do id do Claritio?**
Não. Onde cabe um colaborador, cabe a matrícula que você já usa.

**A chave vence?**
Não. Ela vale até alguém revogar.

**Perdi a chave.**
Crie outra e revogue a antiga. Ninguém consegue recuperá-la — nem nós.

**Dá para criar colaborador pela API?**
Ainda não. Admitir alguém envolve escala, turno e documentos, e uma criação
pela metade seria pior que nenhuma. Hoje a API lê cadastro e escreve ponto.

**Como sei que a empresa tem a API?**
Chame `/ping`. Se responder 403 dizendo que a API não está ativa, é plano.

**Vocês mandam webhook quando algo muda?**
Ainda não. Por enquanto, pergunte com `desde` — é barato e não exige que
você exponha um endereço.

**Posso chamar do navegador?**
Tecnicamente sim (a API responde a qualquer origem), mas não faça isso com uma
chave de produção: qualquer visitante veria a chave. Do navegador, só com a
chave do simulador.

## Mudanças

Dentro do `/v1`, prometemos:

- **não** remover campo nem rota;
- **não** mudar o tipo nem o significado de um campo existente;
- **poder** acrescentar campos novos — então ignore o que você não conhece, em
  vez de recusar a resposta.

Mudança que quebre alguma dessas promessas sai como `/v2`, e o `/v1`
continua no ar.

| Quando | O quê |
|---|---|
| 27/09/2026 | `v1` publicada: colaboradores, batidas, ocorrências e espelho |

---
Claritio · https://claritio.com.br · claritio@claritio.com.br
