# iopoint · API Customer V2 — Guia para IAs

Este documento descreve, de ponta a ponta, como uma IA (LLM, agente, integração automatizada) deve consumir a **API Customer V2** do iopoint. É a referência canônica derivada da mesma fonte de dados que alimenta o portal de documentação humano.

## Visão geral

- **Base URL:** `https://api.iopoint.com.br/api/customer/v2`
- **Escopo:** todas as rotas operam **automaticamente** sobre a empresa associada ao token. Não há `company_id` para enviar — o middleware identifica a empresa pelo header. Em grupos econômicos, um token de **matriz** pode acessar as filiais nos endpoints `GET` (ver _Grupos econômicos_).
- **Versionamento:** apenas a V2 é suportada. A V1 está marcada para descontinuação e não deve ser usada em integrações novas.
- **Formato:** JSON em todas as respostas. Bodies são `application/json` salvo quando indicado `multipart/form-data` (upload de arquivos).

## Autenticação

Toda requisição **precisa** do header `apiIopointToken` contendo o token estático da empresa. Não há OAuth, refresh nem expiração de sessão.

```http
apiIopointToken: SEU_TOKEN_AQUI
```

**Como obter o token:** um usuário com perfil de _gestor administrador_ acessa, na plataforma iopoint, `Configurações → Empresa → Token API` e copia o valor (ou clica em _Gerar novo token_ caso ainda não exista).

**Regras importantes:**

- O token é **por empresa**. Em grupos econômicos, a empresa **matriz** pode, de forma opt-in e somente em `GET`, acessar dados das filiais (ver _Grupos econômicos_). Filiais enxergam apenas a si mesmas.
- Token ausente, inválido, malformado ou de empresa inativa devolve **401** com `error.code = invalid_iopoint_token`.
- Trate o token como senha: nunca exponha em apps mobile, código front-end público ou logs.

## Convenções de resposta

### Envelope de sucesso

```json
{
  "data": [
    {
      "id": 1,
      "description": "Recursos Humanos"
    }
  ],
  "meta": {
    "begin_date": "2026-05-01",
    "end_date": "2026-05-31"
  }
}
```

### Envelope de erro

```json
{
  "error": {
    "code": "date_range_exceeded",
    "message": "O período máximo é de 31 dias."
  }
}
```

Erros de validação (422) também incluem `payload_data_required` com a lista de campos faltantes:

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Campos obrigatórios ausentes."
  },
  "payload_data_required": [
    "begin_date",
    "end_date"
  ]
}
```

### Status HTTP

| Código | Significado |
| --- | --- |
| 200 | Sucesso. GETs e algumas mutações retornam payload em `data`. |
| 201 | Recurso criado (POST que cria entidade). |
| 400 | Sintaxe inválida na requisição. |
| 401 | Token ausente ou inválido (`invalid_iopoint_token`). |
| 403 | Erro genérico do servidor / integração externa rejeitou. |
| 404 | Recurso não encontrado ou de outra empresa. |
| 422 | Falha de validação. Retorna `payload_data_required` quando aplicável. |

### Datas, horários e durações

- Datas: `YYYY-MM-DD` (ex.: `2026-05-26`).
- Datas com hora: `YYYY-MM-DD HH:MM:SS` (ex.: `2026-05-26 08:00:00`).
- Fuso: horário local da empresa (Brasília por padrão).
- Durações: `HH:MM:SS`, com sinal quando aplicável (`-00:15:00`).
- Parâmetro opcional `decimal_format=1`: converte durações para decimal (ex.: `08:30:00` → `8.5`, `00:00:00` → `0`). Disponível em endpoints de horas.

### Períodos de consulta

Endpoints que aceitam `begin_date` e `end_date` limitam o intervalo a **31 dias**. Períodos maiores devolvem **422 `date_range_exceeded`**.

Endpoints afetados: `collaborator/totalHours`, `point/getFromPeriod`, `absence/getFromPeriod`, `tardiness`, `adjustment`, `inconsistency`.

### Parâmetros do tipo lista (arrays)

Endpoints de filtro aceitam listas em query (GET) ou body (POST/`multipart`). O nome do parâmetro **sempre** termina com `[]`. Para enviar múltiplos valores, **repita a chave** uma vez para cada item:

```
?national_registry_list[]=12345678900&national_registry_list[]=98765432100
```

Regras práticas:

- Os colchetes `[]` no **nome** são obrigatórios mesmo para um único item (`?national_registry_list[]=12345678900`). Enviar `national_registry_list=...` (sem `[]`) é rejeitado com 422.
- **Não** envie JSON dentro do valor (ex.: `national_registry_list=["123"]`) nem CSV (`national_registry_list=123,456`) — ambos são rejeitados.
- Em `multipart/form-data`, a mesma regra vale: repita o campo `name[]` para cada item. Para uploads (`attachment[]`), envie um arquivo por entry.
- Cliente em **JavaScript (`fetch`/`URLSearchParams`)**: use `params.append("national_registry_list[]", "12345678900")` — não `params.set`.
- Cliente em **Python (`requests`)**: passe `params={"national_registry_list[]": ["12345678900", "98765432100"]}` e o `requests` repete a chave automaticamente.
- Cliente em **PHP (`http_build_query`)**: `http_build_query(["national_registry_list" => [...]])` gera a sintaxe correta automaticamente.
- Cliente em **cURL**: encadeie `-d` ou inclua os pares na URL: `-G --data-urlencode "national_registry_list[]=12345678900" --data-urlencode "national_registry_list[]=98765432100"`.
- **Postman**: na aba **Params** (para GET) ou **Body → form-data** (para multipart), adicione uma linha por valor usando a chave terminada em `[]` (ex.: `national_registry_list[]`).

### Listas vazias

Quando nenhum dado é encontrado a resposta é **200** com `{ "data": [] }`. Endpoints de período mantêm o `meta` com os filtros usados.

### Grupos econômicos (matriz e filiais)

Quando o token é de uma **matriz** (empresa cujo `adm_company_id` é nulo e que tem filiais apontando para ela), todos os endpoints `GET` aceitam dois parâmetros opcionais para acessar as filiais do grupo. Sem eles, o escopo é apenas a própria empresa (comportamento padrão e retrocompatível). **Vale apenas para `GET`** — escritas sempre operam na empresa do token. Filiais enxergam apenas a si mesmas.

| Parâmetro | Efeito |
| --- | --- |
| `include_branches=1` | Agrega a matriz e todas as filiais na resposta. |
| `company_national_registry=<CNPJ>` | Restringe a uma empresa específica do grupo. CNPJ fora do grupo acessível devolve **404 `company_not_found`**. |

Descubra os CNPJs do grupo em `GET /customer/v2/economic-group` (lista matriz + filiais, cada uma com `is_headquarter`). Toda resposta de leitura traz um bloco `company` (`name` + `national_registry`) identificando a empresa de origem de cada registro.

**Buscar um colaborador que está numa filial:** os filtros de colaborador (`national_registry_list[]`, `email_list[]`, `national_registry`) são combinados **com** o escopo de empresa. Para encontrar alguém de uma filial, envie o filtro do colaborador **junto** com `include_branches=1` (procura no grupo todo) ou `company_national_registry` (procura só naquela filial). Sem um dos dois, o escopo é só a matriz e o colaborador da filial não é encontrado.

```
GET /customer/v2/point/getFromPeriod?begin_date=2026-05-01&end_date=2026-05-31&include_branches=1&national_registry_list[]=12345678900
```

- Busca por **e-mail** (`email_list[]`): disponível em `collaborator/totalHours` e `point/getFromPeriod`. Os relatórios `tardiness`, `adjustment`, `overtime` e `inconsistency` filtram apenas por `national_registry` (CPF).
- **CPF repetido no grupo:** se a mesma pessoa for colaboradora em mais de uma empresa, `include_branches=1` retorna uma ocorrência por empresa — use o bloco `company` para distinguir, ou `company_national_registry` para trazer só uma.

## Bloco do colaborador

Vários endpoints (`collaborator/totalHours`, `point/getFromPeriod`, `tardiness`, `adjustment`, `overtime`, `inconsistency`, `absence/getFromPeriod`) reaproveitam o mesmo bloco de identificação do colaborador:

```json
{
  "national_registry": "12345678900",
  "registration_number": "0042",
  "email": "joao.silva@empresa.com.br",
  "name": "João da Silva",
  "occupation": "Analista de RH",
  "department": "Recursos Humanos",
  "team": null,
  "business_unit": "Matriz",
  "admission_date": "2022-03-15",
  "pis": "12345678901",
  "company": {
    "name": "Filial São Paulo LTDA",
    "trading_name": "Filial SP",
    "national_registry": "12345678000288"
  }
}
```

## Catálogo de recursos

- [Ajustes de ponto](#ajustes-de-ponto-adjustment) — Listar solicitações de ajuste (pendentes, aprovadas, recusadas).
- [Atrasos](#atrasos-tardiness) — Listar atrasos detectados no período.
- [Ausências](#aus-ncias-absence) — Tipos de ausência, listagem por período, anexos e criação.
- [Cercas digitais](#cercas-digitais-barrier) — Listar cercas digitais cadastradas.
- [Cargos](#cargos-occupation) — Listar e criar cargos disponíveis na empresa.
- [Centros de custo](#centros-de-custo-cost-center) — Listar e criar centros de custo.
- [Colaboradores](#colaboradores-collaborator) — Listar, criar, demitir e enviar foto facial de colaboradores.
- [Configurações de colaborador](#configura-es-de-colaborador-collaborator-settings) — Conjuntos de configurações aplicáveis a colaboradores.
- [Departamentos](#departamentos-department) — Listar e criar departamentos.
- [Empresa](#empresa-company) — Dados cadastrais da empresa autenticada.
- [Grupo econômico](#grupo-econ-mico-economic-group) — Listar a matriz e as filiais acessíveis pelo token, com os CNPJs usados para mirar empresas específicas.
- [Horas extras / Banco](#horas-extras-banco-overtime) — Saldo de horas extras e banco em uma data específica.
- [Inconsistências](#inconsist-ncias-inconsistency) — Ocorrências de inconsistência (intra/inter jornada e referência de HE).
- [Escalas](#escalas-journey) — Listar escalas ativas.
- [Pontos](#pontos-point) — Listar pontos do período, registrar novos pontos e obter foto de auditoria.
- [Regras de ponto](#regras-de-ponto-point-rule) — Listar regras de ponto disponíveis para os colaboradores.
- [Tipos de demissão](#tipos-de-demiss-o-fired-type) — Listar e criar tipos de demissão.
- [Unidades](#unidades-unit) — Listar unidades de negócio.

## Ajustes de ponto (`adjustment`)

Listar solicitações de ajuste (pendentes, aprovadas, recusadas).

### GET /customer/v2/adjustment

**Ajustes no período**

Lista solicitações de ajuste de ponto realizadas pelos colaboradores no período. Cada item indica o status (Pendente/Aprovado/Recusado), justificativa do colaborador e observação do gestor.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `begin_date` | date | sim | Início do período (YYYY-MM-DD). Exemplo: `2026-05-01`. |
| `end_date` | date | sim | Fim do período (YYYY-MM-DD). Máximo de 31 dias. Exemplo: `2026-05-31`. |
| `national_registry` | string | não | CPF do colaborador para filtrar. Opcional. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/adjustment" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "national_registry": "12345678900",
      "registration_number": "0042",
      "email": "joao.silva@empresa.com.br",
      "name": "João da Silva",
      "occupation": "Analista de RH",
      "department": "Recursos Humanos",
      "team": null,
      "business_unit": "Matriz",
      "admission_date": "2022-03-15",
      "pis": "12345678901",
      "company": {
        "name": "Filial São Paulo LTDA",
        "trading_name": "Filial SP",
        "national_registry": "12345678000288"
      },
      "adjustments": [
        {
          "date": "2026-05-12",
          "requests_in_day": 1,
          "type": "Ajuste de ponto",
          "status": "Aprovado",
          "collaborator_reason": "Esqueci de bater a saída",
          "manager_observation": "Confirmado pela equipe",
          "approved_by": "Maria Oliveira",
          "created_at": "2026-05-12 18:05:00",
          "updated_at": "2026-05-13 09:20:00"
        }
      ]
    }
  ],
  "meta": {
    "begin_date": "2026-05-01",
    "end_date": "2026-05-31"
  }
}
```

**Erros**

- **422** `date_range_exceeded` — Período maior que 31 dias.

## Atrasos (`tardiness`)

Listar atrasos detectados no período.

### GET /customer/v2/tardiness

**Atrasos no período**

Lista os atrasos detectados por colaborador. O algoritmo considera atraso quando a batida de entrada ocorre após o início da jornada somado à tolerância configurada, e antes de 2 horas após o início (acima disso é tratado como falta).

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `begin_date` | date | sim | Início do período (YYYY-MM-DD). Exemplo: `2026-05-01`. |
| `end_date` | date | sim | Fim do período (YYYY-MM-DD). Máximo de 31 dias. Exemplo: `2026-05-31`. |
| `national_registry` | string | não | CPF do colaborador para filtrar. Opcional. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/tardiness" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "national_registry": "12345678900",
      "registration_number": "0042",
      "email": "joao.silva@empresa.com.br",
      "name": "João da Silva",
      "occupation": "Analista de RH",
      "department": "Recursos Humanos",
      "team": null,
      "business_unit": "Matriz",
      "admission_date": "2022-03-15",
      "pis": "12345678901",
      "company": {
        "name": "Filial São Paulo LTDA",
        "trading_name": "Filial SP",
        "national_registry": "12345678000288"
      },
      "tardiness": [
        {
          "date": "2026-05-12",
          "journey_in": "08:00",
          "punch_in": "08:17",
          "minutes_late": "00:17",
          "all_points": [
            "08:17",
            "12:00",
            "13:00",
            "17:00"
          ]
        }
      ]
    }
  ],
  "meta": {
    "begin_date": "2026-05-01",
    "end_date": "2026-05-31"
  }
}
```

**Erros**

- **422** `date_range_exceeded` — Período maior que 31 dias.

## Ausências (`absence`)

Tipos de ausência, listagem por período, anexos e criação.

### GET /customer/v2/absence/types

**Listar tipos de ausência**

Retorna os tipos de ausência disponíveis (tanto os globais quanto os personalizados da empresa), com flags de comportamento.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/absence/types" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "description": "Atestado médico",
      "paid_leave": true,
      "comp_time": false,
      "compensation": false,
      "can_request_app": true
    },
    {
      "id": 2,
      "description": "Férias",
      "paid_leave": true,
      "comp_time": false,
      "compensation": false,
      "can_request_app": false
    }
  ]
}
```

### GET /customer/v2/absence/getFromPeriod

**Ausências do período**

Lista ausências/férias aprovadas que se sobrepõem ao período informado. Estrutura é ausência-cêntrica: cada item traz o tipo, datas, detalhes médicos e os colaboradores envolvidos.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `begin_date` | datetime | sim | Início do período (YYYY-MM-DD HH:MM:SS). Exemplo: `2026-05-01 00:00:00`. |
| `end_date` | datetime | sim | Fim do período (YYYY-MM-DD HH:MM:SS). Exemplo: `2026-05-31 23:59:59`. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/absence/getFromPeriod" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "absence_id": 4521,
      "absence_type_id": 1,
      "type": "Atestado médico",
      "description": "Atestado de 3 dias",
      "begin_date": "2026-05-12 00:00:00",
      "end_date": "2026-05-14 23:59:59",
      "days": 3,
      "reference_date": "2026-05-12",
      "details": "Repouso domiciliar",
      "comp_time": false,
      "paid_leave": true,
      "full_day": true,
      "sum_on_work_time": false,
      "sum_total_on_work_time": false,
      "cr_register": "CRM/SP 123456",
      "professional_name": "Dr. Carlos Mendes",
      "health_unit": "Hospital Exemplo",
      "cid_description": "Infecção respiratória aguda",
      "cid": [
        "J06.9"
      ],
      "has_attachment": true,
      "collaborators": [
        {
          "national_registry": "12345678900",
          "registration_number": "0042",
          "email": "joao.silva@empresa.com.br",
          "name": "João da Silva",
          "occupation": "Analista de RH",
          "department": "Recursos Humanos",
          "team": null,
          "business_unit": "Matriz",
          "admission_date": "2022-03-15",
          "pis": "12345678901",
          "company": {
            "name": "Filial São Paulo LTDA",
            "trading_name": "Filial SP",
            "national_registry": "12345678000288"
          }
        }
      ]
    }
  ],
  "meta": {
    "begin_date": "2026-05-01 00:00:00",
    "end_date": "2026-05-31 23:59:59"
  }
}
```

### GET /customer/v2/absence/attachment

**Anexos da ausência**

Retorna os anexos (atestados, comprovantes) de uma ausência em base64. Devolve `data: []` quando não há anexos.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `absence_id` | integer | sim | ID da ausência. Exemplo: `4521`. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/absence/attachment" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "filename": "atestado-2026-05-12.pdf",
      "mime_type": "application/pdf",
      "base64": "JVBERi0xLjQKJcfsj6IK..."
    }
  ],
  "meta": {
    "absence_id": 4521
  }
}
```

**Erros**

- **404** `not_found` — Ausência inexistente ou de outra empresa.

### POST /customer/v2/absence

**Criar ausência**

Cria uma nova ausência para um ou mais colaboradores (identificados pelo CPF). Aceita anexos via `multipart/form-data`.

**Body (multipart/form-data)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `national_registry[]` | array<string> | sim | CPFs dos colaboradores ausentes (somente dígitos). Repita a chave para cada CPF: `national_registry[]=12345678900&national_registry[]=98765432100`. Os colchetes `[]` no nome são obrigatórios mesmo para um único CPF. |
| `absence_type_id` | integer | sim | ID do tipo de ausência (ver `GET /absence/types`). |
| `description` | string | sim | Descrição curta. |
| `details` | string | sim | Detalhamento/observações. |
| `begin_date` | date | sim | Início (YYYY-MM-DD). |
| `end_date` | date | sim | Fim (YYYY-MM-DD). |
| `paid` | boolean | sim | `1` para ausência remunerada, `0` caso contrário. |
| `full_day` | boolean | sim | `1` para dia inteiro, `0` para parcial. |
| `sum_on_work_time` | boolean | sim | Somar no tempo trabalhado diário. |
| `sum_total_on_work_time` | boolean | sim | Somar no total trabalhado do período. |
| `attachment[]` | file | não | Arquivos anexos (atestado, comprovantes). Opcional. |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/absence" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -F "national_registry=12345678900" \
  -F "absence_type_id=1" \
  -F "description=Atestado de 2 dias" \
  -F "details=Apresentou atestado médico" \
  -F "begin_date=2026-05-26" \
  -F "end_date=2026-05-27" \
  -F "paid=1" \
  -F "full_day=1" \
  -F "sum_on_work_time=1" \
  -F "sum_total_on_work_time=1"
```

**Resposta 201**

```json
{
  "data": {
    "absence_id": 4522
  }
}
```

**Erros**

- **404** `absence_type_not_found` — absence_type_id inválido.

## Cercas digitais (`barrier`)

Listar cercas digitais cadastradas.

### GET /customer/v2/barrier

**Listar cercas digitais**

Retorna a lista de cercas digitais ativas da empresa. Cercas inativas não aparecem na listagem.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/barrier" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "name": "Sede"
    },
    {
      "id": 2,
      "name": "Filial Centro"
    }
  ]
}
```

## Cargos (`occupation`)

Listar e criar cargos disponíveis na empresa.

### GET /customer/v2/occupation

**Listar cargos**

Retorna os cargos ativos cadastrados para a empresa. Cargos inativos não aparecem na listagem.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/occupation" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "description": "Analista de RH"
    },
    {
      "id": 2,
      "description": "Operador de caixa"
    }
  ]
}
```

### POST /customer/v2/occupation

**Criar cargo**

Cria um novo cargo para a empresa autenticada.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `description` | string | sim | Nome do cargo. |
| `number_cbo` | string | não | Código CBO. Opcional. |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/occupation" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"description":"Analista de QA","number_cbo":"2521-05"}'
```

**Resposta 201**

```json
{
  "data": {
    "id": 42
  }
}
```

**Erros**

- **422** `invalid_request_payload` — Campo `description` não informado ou vazio.

## Centros de custo (`cost-center`)

Listar e criar centros de custo.

### GET /customer/v2/cost-center

**Listar centros de custo**

Retorna a lista de centros de custo ativos da empresa. Centros de custo inativos não aparecem.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/cost-center" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "name": "Matriz - SP"
    },
    {
      "id": 2,
      "name": "Filial - RJ"
    }
  ]
}
```

### POST /customer/v2/cost-center

**Criar centro de custo**

Cria um novo centro de custo para a empresa autenticada. O centro de custo é sempre criado como ativo — não há opção de criar inativo via API.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `name` | string | sim | Nome do centro de custo. |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/cost-center" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"name":"Filial - MG"}'
```

**Resposta 201**

```json
{
  "data": {
    "id": 7
  }
}
```

**Erros**

- **422** `invalid_request_payload` — Campo `name` não informado ou vazio.

## Colaboradores (`collaborator`)

Listar, criar, demitir e enviar foto facial de colaboradores.

### GET /customer/v2/collaborator

**Listar colaboradores ativos**

Retorna todos os colaboradores ativos da empresa, com o bloco padrão de identificação.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/collaborator" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "national_registry": "12345678900",
      "registration_number": "0042",
      "email": "joao.silva@empresa.com.br",
      "name": "João da Silva",
      "occupation": "Analista de RH",
      "department": "Recursos Humanos",
      "team": null,
      "business_unit": "Matriz",
      "admission_date": "2022-03-15",
      "pis": "12345678901",
      "company": {
        "name": "Filial São Paulo LTDA",
        "trading_name": "Filial SP",
        "national_registry": "12345678000288"
      }
    }
  ]
}
```

### GET /customer/v2/collaborator/totalHours

**Totais de horas por colaborador**

Agrega todos os tipos de horas (banco, faltas, atestados, noturno, horas extras 1/2/3/4, intrajornada, interjornada, DSR, feriados, trabalhada etc.) por colaborador em um período de até 31 dias. Suporta filtro por CPF ou e-mail e formato decimal opcional.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `begin_date` | date | sim | Data inicial do período (YYYY-MM-DD). Exemplo: `2026-05-01`. |
| `end_date` | date | sim | Data final do período (YYYY-MM-DD). Máximo de 31 dias a partir de `begin_date`. Exemplo: `2026-05-31`. |
| `national_registry_list[]` | array<string> | não | Lista de CPFs (somente dígitos) para filtrar. Opcional. Use a sintaxe PHP/HTML padrão repetindo a chave: `national_registry_list[]=12345678900&national_registry_list[]=98765432100`. Mesmo com um único CPF, os colchetes `[]` no nome são obrigatórios. Exemplo: `["12345678900","98765432100"]`. |
| `email_list[]` | array<string> | não | Lista de e-mails para filtrar. Opcional. Mesma sintaxe da `national_registry_list[]`: repita a chave para cada e-mail, ex.: `email_list[]=fulano@empresa.com.br`. Exemplo: `["fulano@empresa.com.br"]`. |
| `decimal_format` | boolean | não | Quando `1`, devolve as horas em formato decimal (ex.: `8.50`) em vez de `HH:MM:SS`. Exemplo: `1`. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/collaborator/totalHours?begin_date=2026-05-01&end_date=2026-05-31" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "national_registry": "12345678900",
      "registration_number": "0042",
      "email": "joao.silva@empresa.com.br",
      "name": "João da Silva",
      "occupation": "Analista de RH",
      "department": "Recursos Humanos",
      "team": null,
      "business_unit": "Matriz",
      "admission_date": "2022-03-15",
      "pis": "12345678901",
      "company": {
        "name": "Filial São Paulo LTDA",
        "trading_name": "Filial SP",
        "national_registry": "12345678000288"
      },
      "total_hours": {
        "worked_time": "176:00:00",
        "worked_actual_time": "170:15:00",
        "bank_time": "04:30:00",
        "bank_time_factored": "06:45:00",
        "fault_full_time": "08:00:00",
        "fault_partial_time": "00:00:00",
        "interjourney": "00:00:00",
        "intrajourney": "00:00:00",
        "justified_time": "00:00:00",
        "justified_not_paid_time": "00:00:00",
        "medical_certificate_time": "00:00:00",
        "night_time": "00:00:00",
        "night_time_reduced": "00:00:00",
        "over_time_1": "10:00:00",
        "over_time_1_day": "08:30:00",
        "over_time_1_night": "01:30:00",
        "over_time_1_night_reduced": "01:42:51",
        "over_time_2": "02:00:00",
        "over_time_2_day": "02:00:00",
        "over_time_2_night": "00:00:00",
        "over_time_2_night_reduced": "00:00:00",
        "over_time_3": "00:00:00",
        "over_time_3_day": "00:00:00",
        "over_time_3_night": "00:00:00",
        "over_time_3_night_reduced": "00:00:00",
        "over_time_4": "00:00:00",
        "over_time_4_day": "00:00:00",
        "over_time_4_night": "00:00:00",
        "over_time_4_night_reduced": "00:00:00",
        "over_time_dsr": "00:00:00",
        "over_time_dsr_day": "00:00:00",
        "over_time_dsr_night": "00:00:00",
        "over_time_dsr_night_reduced": "00:00:00",
        "over_time_holiday": "00:00:00",
        "over_time_holiday_day": "00:00:00",
        "over_time_holiday_night": "00:00:00",
        "over_time_holiday_night_reduced": "00:00:00"
      }
    }
  ],
  "meta": {
    "begin_date": "2026-05-01",
    "end_date": "2026-05-31"
  }
}
```

**Erros**

- **422** `date_range_exceeded` — Período maior que 31 dias.
- **401** `invalid_iopoint_token` — Token ausente ou inválido.

**Notas**

- O período máximo é de 31 dias — solicitações maiores retornam `date_range_exceeded`.
- Quando `decimal_format=1`, valores `00:00:00` viram `0` e horas viram número (ex.: `8.5`).

### POST /customer/v2/collaborator

**Criar colaborador**

Cria um novo colaborador vinculado à empresa. Todos os IDs referenciados precisam existir e pertencer à empresa autenticada.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `name` | string | sim | Nome completo. |
| `national_registry` | string | sim | CPF (somente dígitos). |
| `email` | string | sim | E-mail do colaborador. |
| `birth_date` | date | sim | Data de nascimento (YYYY-MM-DD). |
| `registration_number` | string | não | Matrícula. |
| `begin_date` | date | sim | Data a partir da qual o colaborador passa a registrar ponto na iopoint (YYYY-MM-DD). |
| `admission_date` | date | não | Data formal de admissão na empresa (YYYY-MM-DD). Opcional. |
| `pis` | string | não | Número do PIS. |
| `journey_id` | integer | sim | ID da jornada (ver `GET /journey`). |
| `cost_center_id` | integer | sim | ID do centro de custo. |
| `department_id` | integer | sim | ID do departamento. |
| `unit_id` | integer | sim | ID da unidade. |
| `collaborator_settings_id` | integer | sim | ID das configurações. |
| `point_rule_id` | integer | sim | ID da regra de ponto. |
| `occupation_id` | integer | não | ID do cargo. |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/collaborator" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"name":"João da Silva","national_registry":"12345678900","email":"joao.silva@empresa.com.br","birth_date":"1990-05-20","registration_number":"0042","begin_date":"2026-05-26","admission_date":"2026-05-26","journey_id":3,"cost_center_id":5,"department_id":2,"unit_id":1,"collaborator_settings_id":1,"point_rule_id":4}'
```

**Resposta 201**

```json
{
  "data": {
    "id": 1042
  }
}
```

**Erros**

- **404** `journey_not_found` — journey_id inexistente ou de outra empresa.
- **404** `cost_center_not_found` — cost_center_id inválido.
- **404** `department_not_found` — department_id inválido.
- **404** `unit_not_found` — unit_id inválido.
- **404** `collaborator_settings_not_found` — collaborator_settings_id inválido.
- **404** `point_rule_not_found` — point_rule_id inválido.

### POST /customer/v2/collaborator/photo

**Enviar foto facial**

Envia a foto facial do colaborador (em base64) para reconhecimento facial. O colaborador é identificado pelo CPF (`national_registry`); se houver mais de um colaborador com o mesmo CPF na empresa, o ponto sobe no ativo (`dismissal_date IS NULL`). A imagem deve ser nítida, frontal e sem acessórios.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `national_registry` | string | sim | CPF do colaborador (somente dígitos). Zeros à esquerda são preenchidos automaticamente até 11 caracteres. |
| `photo_base64` | base64 | sim | Imagem JPEG/PNG codificada em base64 (sem o prefixo `data:image/...`). |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/collaborator/photo" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"national_registry":"12345678900","photo_base64":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAg..."}'
```

**Resposta 200**

```json
{
  "data": {
    "success": true
  }
}
```

**Erros**

- **404** `cpf_not_found` — CPF não cadastrado no sistema.
- **404** `collaborator_not_found` — CPF existe, mas não há colaborador vinculado na empresa do token.
- **422** `collaborator_fired` — Único colaborador encontrado com esse CPF na empresa está demitido (`dismissal_date` preenchida); upload de foto bloqueado.
- **403** `invalid_photo` — Imagem rejeitada (sem rosto, baixa qualidade).
- **403** `face_recognition_failed` — Falha ao processar a foto facial.

### PUT /customer/v2/collaborator/dismissal

**Demitir colaborador**

Registra a demissão de um colaborador. Pelo menos um identificador (`collaborator_id`, `registration_number` ou `national_registry`) deve ser informado.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `dismissal_date` | date | sim | Data da demissão (YYYY-MM-DD). |
| `fired_type_id` | integer | sim | ID do tipo de demissão (ver `GET /fired-type`). |
| `collaborator_id` | integer | não | ID do colaborador (use um dos identificadores). |
| `registration_number` | string | não | Matrícula do colaborador. |
| `national_registry` | string | não | CPF do colaborador (somente dígitos). |
| `fired_description` | string | não | Observações da demissão. |

**Exemplo (cURL)**

```bash
curl -X PUT "https://api.iopoint.com.br/api/customer/v2/collaborator/dismissal" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"national_registry":"12345678900","dismissal_date":"2026-05-31","fired_type_id":2,"fired_description":"Demissão sem justa causa."}'
```

**Resposta 200**

```json
{
  "data": {
    "success": true
  }
}
```

**Erros**

- **404** `collaborator_not_found` — Nenhum identificador resolve para um colaborador da empresa.
- **404** `fired_type_not_found` — fired_type_id inválido.
- **422** `dismissal_date_before_admission_date` — Data da demissão anterior à admissão.

## Configurações de colaborador (`collaborator-settings`)

Conjuntos de configurações aplicáveis a colaboradores.

### GET /customer/v2/collaborator-settings

**Listar configurações de colaborador**

Retorna os pacotes de configurações ativos (perfil de batida, validações, comportamentos) que podem ser vinculados ao colaborador na criação. Configurações inativas não aparecem na listagem.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/collaborator-settings" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "description": "Padrão"
    },
    {
      "id": 2,
      "description": "Home office sem validação de localização"
    }
  ]
}
```

## Departamentos (`department`)

Listar e criar departamentos.

### GET /customer/v2/department

**Listar departamentos**

Retorna todos os departamentos ativos da empresa.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/department" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "description": "Recursos Humanos"
    },
    {
      "id": 2,
      "description": "Operação"
    },
    {
      "id": 3,
      "description": "Financeiro"
    }
  ]
}
```

### POST /customer/v2/department

**Criar departamento**

Cria um novo departamento ativo na empresa.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `description` | string | sim | Nome do departamento. |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/department" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"description":"Tecnologia da Informação"}'
```

**Resposta 201**

```json
{
  "data": {
    "id": 7
  }
}
```

## Empresa (`company`)

Dados cadastrais da empresa autenticada.

### GET /customer/v2/company

**Obter dados da empresa**

Retorna os dados cadastrais da empresa associada ao token: razão social, nome fantasia, endereço, contatos e identificadores fiscais (CNPJ, CEI, CAEPF, CNO).

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/company" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": {
    "name": "Empresa Exemplo LTDA",
    "trading_name": "Exemplo",
    "national_registry": "12345678000199",
    "cei": null,
    "caepf": null,
    "cno": null,
    "address": "Av. Paulista",
    "address_number": "1000",
    "complement": "Sala 101",
    "neighborhood": "Bela Vista",
    "zip_code": "01310100",
    "phone": "1140040000",
    "email": "contato@exemplo.com.br"
  }
}
```

**Notas**

- Grupos econômicos: `company_national_registry` (CNPJ) retorna os dados de uma filial específica como objeto único; `include_branches=1` retorna a matriz e as filiais como lista (`data` vira array).

## Grupo econômico (`economic-group`)

Listar a matriz e as filiais acessíveis pelo token, com os CNPJs usados para mirar empresas específicas.

### GET /customer/v2/economic-group

**Listar empresas do grupo**

Lista a matriz e as filiais do grupo econômico acessíveis pelo token. Para token de matriz, retorna a matriz e todas as filiais ativas; para token de filial, retorna apenas a própria empresa. Os CNPJs (`national_registry`) retornados aqui são os valores aceitos no parâmetro `company_national_registry` dos demais endpoints.

O vínculo de grupo econômico liga cada filial à sua matriz. Com o token da matriz, este endpoint é o ponto de partida para descobrir quais empresas você pode consultar e com quais CNPJs mirá-las individualmente.

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/economic-group" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "name": "Matriz LTDA",
      "trading_name": "Matriz",
      "national_registry": "12345678000199",
      "is_headquarter": true
    },
    {
      "name": "Filial São Paulo LTDA",
      "trading_name": "Filial SP",
      "national_registry": "12345678000288",
      "is_headquarter": false
    }
  ]
}
```

**Notas**

- Acesso ao grupo é exclusivo de tokens de matriz; filiais enxergam apenas a si mesmas.
- Use o `national_registry` retornado aqui em `company_national_registry` para consultar uma empresa específica em qualquer endpoint GET, ou `include_branches=1` para agregar o grupo todo.

## Horas extras / Banco (`overtime`)

Saldo de horas extras e banco em uma data específica.

### GET /customer/v2/overtime

**Saldo do dia**

Retorna o regime do colaborador (BH, HE, Híbrido) e os componentes do dia: total de horas extras, horas faltantes, intervalo, normais, saldo do dia, saldo acumulado e crédito/débito acumulados separados.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `date` | date | sim | Data de referência (YYYY-MM-DD). Exemplo: `2026-05-26`. |
| `national_registry` | string | não | CPF do colaborador para filtrar. Opcional. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/overtime" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "national_registry": "12345678900",
      "registration_number": "0042",
      "email": "joao.silva@empresa.com.br",
      "name": "João da Silva",
      "occupation": "Analista de RH",
      "department": "Recursos Humanos",
      "team": null,
      "business_unit": "Matriz",
      "admission_date": "2022-03-15",
      "pis": "12345678901",
      "company": {
        "name": "Filial São Paulo LTDA",
        "trading_name": "Filial SP",
        "national_registry": "12345678000288"
      },
      "regime": "BH",
      "total_overtime": "01:30:00",
      "missing_hours": "00:00:00",
      "interval_hours": "01:00:00",
      "normal_hours": "08:00:00",
      "day_balance": "01:30:00",
      "accumulated_balance": "12:15:00",
      "credit": "18:45:00",
      "debt": "06:30:00"
    }
  ],
  "meta": {
    "date": "2026-05-26"
  }
}
```

**Notas**

- Valores `HH:MM:SS`. Regime pode ser `BH`, `HE`, `Híbrido (BH)` ou `Híbrido (HE)`.
- `credit` e `debt` representam, respectivamente, o total bruto creditado (`bank_time_factored`) e debitado (`negative_bank_time`) desde o início da faixa de banco de horas vigente até a data consultada. `accumulated_balance` é o saldo líquido completo, incluindo saldo inicial e pagamentos de banco.

## Inconsistências (`inconsistency`)

Ocorrências de inconsistência (intra/inter jornada e referência de HE).

### GET /customer/v2/inconsistency

**Inconsistências no período**

Lista ocorrências de inconsistência detectadas: intervalo intra-jornada insuficiente, inter-jornada (11h) e horas extras acima do limite. Cada ocorrência traz a data, tipo, valor, justificativa e status (`pending` ou `acknowledged`).

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `begin_date` | date | sim | Início do período (YYYY-MM-DD). Exemplo: `2026-05-01`. |
| `end_date` | date | sim | Fim do período (YYYY-MM-DD). Máximo de 31 dias. Exemplo: `2026-05-31`. |
| `national_registry` | string | não | CPF do colaborador para filtrar. Opcional. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/inconsistency" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "national_registry": "12345678900",
      "registration_number": "0042",
      "email": "joao.silva@empresa.com.br",
      "name": "João da Silva",
      "occupation": "Analista de RH",
      "department": "Recursos Humanos",
      "team": null,
      "business_unit": "Matriz",
      "admission_date": "2022-03-15",
      "pis": "12345678901",
      "company": {
        "name": "Filial São Paulo LTDA",
        "trading_name": "Filial SP",
        "national_registry": "12345678000288"
      },
      "occurrences": [
        {
          "date": "2026-05-13",
          "type": "Intervalo intra-jornada inferior ao mínimo",
          "value": "-00:15:00",
          "justification": null,
          "status": "pending"
        }
      ]
    }
  ],
  "meta": {
    "begin_date": "2026-05-01",
    "end_date": "2026-05-31"
  }
}
```

**Erros**

- **422** `date_range_exceeded` — Período maior que 31 dias.

## Escalas (`journey`)

Listar escalas ativas.

### GET /customer/v2/journey

**Listar escalas**

Retorna as escalas ativas da empresa, utilizadas na criação de colaboradores.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/journey" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "description": "44h semanais — Seg a Sex 08:00-17:00"
    },
    {
      "id": 2,
      "description": "Escala 12x36"
    }
  ]
}
```

## Pontos (`point`)

Listar pontos do período, registrar novos pontos e obter foto de auditoria.

### GET /customer/v2/point/getFromPeriod

**Pontos do período**

Retorna os pontos agrupados por colaborador → dia → batidas, com data/hora, método, origem, geolocalização (latitude/longitude e endereço reverso), informações de ajuste e indicação de foto de auditoria. Os filtros `national_registry_list[]` e `email_list[]` são opcionais — sem eles, retorna todos os colaboradores da empresa no período.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `begin_date` | date | sim | Data inicial (YYYY-MM-DD). Exemplo: `2026-05-01`. |
| `end_date` | date | sim | Data final (YYYY-MM-DD). Máximo de 31 dias. Exemplo: `2026-05-31`. |
| `national_registry_list[]` | array<string> | não | CPFs a filtrar. Opcional — sem este filtro (e sem `email_list[]`), retorna todos os colaboradores da empresa. Use a sintaxe PHP/HTML padrão repetindo a chave: `national_registry_list[]=12345678900&national_registry_list[]=98765432100`. Os colchetes `[]` no nome são obrigatórios mesmo para um único CPF. Exemplo: `["12345678900","98765432100"]`. |
| `email_list[]` | array<string> | não | E-mails a filtrar. Opcional — mesma regra do `national_registry_list[]`. Sintaxe: `email_list[]=fulano@empresa.com.br`. Exemplo: `["fulano@empresa.com.br"]`. |
| `decimal_format` | boolean | não | Devolver `worked_time` em decimal quando `1`. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/point/getFromPeriod?begin_date=2026-05-01&end_date=2026-05-31" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "national_registry": "12345678900",
      "registration_number": "0042",
      "email": "joao.silva@empresa.com.br",
      "name": "João da Silva",
      "occupation": "Analista de RH",
      "department": "Recursos Humanos",
      "team": null,
      "business_unit": "Matriz",
      "admission_date": "2022-03-15",
      "pis": "12345678901",
      "company": {
        "name": "Filial São Paulo LTDA",
        "trading_name": "Filial SP",
        "national_registry": "12345678000288"
      },
      "days": [
        {
          "date": "2026-05-26",
          "shift": "08:00-12:00 / 13:00-17:00",
          "worked_time": "08:00:00",
          "points": [
            {
              "point_id": 9991,
              "datetime": "2026-05-26 07:58:12",
              "hour": "07:58",
              "method": "Reconhecimento facial",
              "origin": "App Mobile",
              "is_adjusted": false,
              "adjustment_reason": null,
              "adjusted_by": null,
              "accuracy_meters": 8,
              "geolocation": {
                "lat": -23.5616,
                "lng": -46.6557
              },
              "address": "Av. Paulista, 1000 - Bela Vista, São Paulo - SP",
              "has_audit_photo": true
            }
          ]
        }
      ]
    }
  ],
  "meta": {
    "begin_date": "2026-05-01",
    "end_date": "2026-05-31"
  }
}
```

**Erros**

- **422** `date_range_exceeded` — Período maior que 31 dias.

**Notas**

- `has_audit_photo: true` indica que existe foto associada ao ponto — use `GET /point/audit` para obtê-la.

### GET /customer/v2/point/audit

**Foto de auditoria do ponto**

Retorna a foto facial registrada no momento da batida em base64, junto com o nome do arquivo e o `mime_type` da imagem.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `point_id` | integer | sim | ID da batida (`point_id` retornado em `getFromPeriod`). Exemplo: `9991`. |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/point/audit?point_id=9991" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": {
    "point_id": 9991,
    "filename": "a3f5c2e1b4d8.jpg",
    "mime_type": "image/jpeg",
    "base64": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAg..."
  },
  "meta": {
    "point_id": 9991
  }
}
```

**Erros**

- **404** `point_not_found` — Ponto inexistente ou de outra empresa.
- **404** `audit_photo_not_found` — Ponto existe, mas não há foto de auditoria associada.

### POST /customer/v2/point

**Registrar ponto**

Registra uma nova batida de ponto via API. A data/hora não pode ser futura nem anterior à admissão. O endpoint devolve o `point_id` e um `hash` SHA-256 que serve como comprovante.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `national_registry` | string | sim | CPF do colaborador (com zeros à esquerda). |
| `datetime` | datetime | sim | Data/hora da batida (YYYY-MM-DD HH:MM:SS). Não pode ser futura. |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/point" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"national_registry":"12345678900","datetime":"2026-05-26 07:58:12"}'
```

**Resposta 201**

```json
{
  "data": {
    "point_id": 9991,
    "hash": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15..."
  }
}
```

**Erros**

- **404** `cpf_not_found` — CPF não cadastrado na empresa.
- **404** `collaborator_not_found` — Colaborador associado ao CPF inativo.
- **422** `collaborator_fired` — Único colaborador encontrado com esse CPF na empresa está demitido (`dismissal_date` preenchida). Se houver duplicidade de CPF, o ponto é registrado no ativo.
- **422** `date_time_greater_than_now` — `datetime` no futuro.
- **422** `date_begin_less_than_now` — `datetime` anterior à data de admissão.

## Regras de ponto (`point-rule`)

Listar regras de ponto disponíveis para os colaboradores.

### GET /customer/v2/point-rule

**Listar regras de ponto**

Retorna as regras de ponto ativas da empresa.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/point-rule" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "description": "Padrão CLT"
    },
    {
      "id": 2,
      "description": "Banco de horas anual"
    }
  ]
}
```

## Tipos de demissão (`fired-type`)

Listar e criar tipos de demissão.

### GET /customer/v2/fired-type

**Listar tipos de demissão**

Retorna os tipos de demissão cadastrados (ex.: sem justa causa, justa causa, pedido).

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/fired-type" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "name": "Sem justa causa"
    },
    {
      "id": 2,
      "name": "Pedido de demissão"
    }
  ]
}
```

### POST /customer/v2/fired-type

**Criar tipo de demissão**

Cria um novo tipo de demissão para a empresa.

**Body (application/json)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `name` | string | sim | Nome do tipo de demissão. |

**Exemplo (cURL)**

```bash
curl -X POST "https://api.iopoint.com.br/api/customer/v2/fired-type" \
  -H "apiIopointToken: SEU_TOKEN_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"name":"Acordo entre as partes"}'
```

**Resposta 201**

```json
{
  "data": {
    "id": 4
  }
}
```

## Unidades (`unit`)

Listar unidades de negócio.

### GET /customer/v2/unit

**Listar unidades**

Retorna as unidades ativas da empresa, ordenadas com a unidade padrão (`is_default = true`) no topo.

**Query params**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `include_branches` | boolean | não | Quando `1`, agrega a matriz e todas as filiais do grupo econômico na resposta. Só leitura. Exemplo: `1`. |
| `company_national_registry` | string | não | CNPJ (apenas dígitos) de uma empresa do grupo para restringir o escopo a ela. Use os CNPJs retornados em `GET /economic-group`. Fora do grupo acessível retorna `company_not_found` (404). Exemplo: `12345678000288`. |

**Exemplo (cURL)**

```bash
curl -X GET "https://api.iopoint.com.br/api/customer/v2/unit" \
  -H "apiIopointToken: SEU_TOKEN_AQUI"
```

**Resposta 200**

```json
{
  "data": [
    {
      "id": 1,
      "name": "Matriz"
    },
    {
      "id": 2,
      "name": "Filial Centro"
    }
  ]
}
```

## Boas práticas para integrações automatizadas

- **Idempotência de leitura:** GETs podem ser repetidos com segurança. Em caso de timeout, reenvie.
- **Idempotência de escrita:** o backend valida duplicidade de pontos pela tupla `(colaborador, datetime)`. Reenviar a mesma batida não cria duplicata, mas pode retornar **422**.
- **Rate limit:** não há limite formal publicado. Para integrações em lote prefira lotes diários por colaborador e respeite o limite de 31 dias por requisição.
- **Tratamento de erros:** trate todas as respostas como `{ data | error }`. Em 422, leia `payload_data_required` para diagnóstico programático.
- **Janela de período:** ao paginar dados históricos, fatie em janelas de 31 dias e itere.
- **Cache de referenciais:** `journey`, `cost-center`, `department`, `unit`, `point-rule`, `collaborator-settings`, `fired-type`, `absence/types`, `occupation` mudam pouco — cacheie localmente (TTL ≥ 1h).
- **Token:** nunca registre o valor do token em logs nem o envie a sistemas de terceiros.

