PontoAgil – Manual da API de Apuração de Ponto

Documentação dos endpoints para integração de dispositivos de ponto (APP) com o sistema PontoAgil.

Sumário

1. Visão Geral

Esta API permite que um aplicativo de ponto (APP) se integre ao sistema PontoAgil para:

  • Validar empresas e dispositivos autorizados.
  • Carregar a lista de funcionários liberados para um dispositivo.
  • Enviar batidas de ponto com imagem e localização.
  • Atualizar batidas (ajustes manuais/aprovações), mantendo o log de evidências.

Base URL (ambiente local)

http://127.0.0.1:8000/api

Formato

  • Entrada e saída em JSON.
  • Codificação UTF-8.

2. Autenticação & Fluxo Geral

2.1 Conceitos principais

Campo Origem Descrição
codigo_empresa Manual (cadastrado no PontoAgil) Código único da empresa para consulta e validação.
chave (dispositivo) Manual (cadastrada no PontoAgil) Chave de liberação inicial do dispositivo, usada na ativação.
chave_app Gerada pelo APP Identificador interno do dispositivo (app). Após ativação, é usada em todas as requisições sensíveis (funcionários, batidas).

2.2 Fluxo resumido do dispositivo

  1. APP recebe manualmente do usuário:
    • codigo_empresa
    • chave (chave de liberação do dispositivo)
  2. APP consulta a empresa:
    • GET /api/empresas/{codigo_empresa}
  3. APP consulta o dispositivo:
    • POST /api/dispositivos/consultar
  4. APP gera uma chave_app (identificador interno do device) e envia para ativação:
    • POST /api/dispositivos/ativar
  5. Com o dispositivo ativo, o APP:
    • Carrega funcionários: GET /api/funcionarios
    • Sincroniza batidas: POST /api/batidas/sincronizar
    • Atualiza batidas/apuração: POST /api/batidas/atualizar
Regra importante: para qualquer dia e funcionário, o sistema aceita no máximo 4 batidas (tanto no sincronizar quanto no atualizar). Acima disso o grupo é recusado.

3. Endpoints de Empresa

GET /empresas/{codigo}

Retorna os dados básicos de uma empresa a partir do seu código.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
codigo string sim Código da empresa (ex.: RP00155).

Resposta – 200 OK (exemplo)

{
  "id": 1,
  "codigo": "RP00155",
  "nome": "Empresa Exemplo LTDA",
  "cnpj": "12.345.678/0001-90",
  "ativo": true
}

Possíveis erros

  • 404 – Empresa não encontrada ou inativa.

4. Endpoints de Dispositivos

POST /dispositivos/consultar

Consulta um dispositivo cadastrado para uma empresa a partir da chave manual.

Body (JSON)

{
  "codigo_empresa": "RP00155",
  "chave": "CHAVE-MANUAL-DO-DISPOSITIVO"
}

Campos

CampoTipoObrigatórioDescrição
codigo_empresa string sim Código da empresa.
chave string sim Chave manual do dispositivo cadastrada no sistema de ponto.

Resposta – 200 OK (exemplo)

{
  "dispositivo_id": 5,
  "empresa_id": 1,
  "filial_id": 2,
  "localizacao_id": 3,
  "tipo_dispositivo": "APP",
  "status": "inativo",
  "nome": "Totem Entrada Loja 01"
}

Possíveis erros

  • 404 – Empresa não encontrada ou inativa.
  • 404 – Dispositivo não encontrado para essa empresa.
POST /dispositivos/ativar

Ativa o dispositivo e associa a chave_app gerada pelo APP.

Body (JSON)

{
  "codigo_empresa": "RP00155",
  "chave": "CHAVE-MANUAL-DO-DISPOSITIVO",
  "chave_app": "APP-DEVICE-UUID-OU-TOKEN"
}

Resposta – 200 OK (exemplo)

{
  "message": "Dispositivo ativado com sucesso.",
  "dispositivo_id": 5,
  "empresa_id": 1,
  "status": "ativo",
  "filial_id": 2,
  "localizacao_id": 3
}

Observações

  • Se o dispositivo já estiver ativo com chave_app, a API apenas retorna os dados e a mensagem “Dispositivo já está ativo.”.

5. Endpoints de Funcionários

GET /funcionarios

Retorna a lista de funcionários ativos para a empresa e dispositivo (chave_app) informados.

Parâmetros (query ou body JSON)

CampoTipoObrigatórioDescrição
codigo_empresa string sim Código da empresa.
chave_app string sim Chave do dispositivo gerada pelo APP e gravada na ativação.

Exemplo de requisição (via query)

GET /api/funcionarios?codigo_empresa=RP00155&chave_app=APP-DEVICE-UUID

Resposta – 200 OK (exemplo)

[
  {
    "id": 10,
    "nome": "João da Silva",
    "cpf": "111.222.333-44",
    "matricula": "FUNC001",
    "cargo": "Vendedor",
    "foto_path": "fotos/func_10.jpg",
    "senha_colaborador": "1234",
    "localizacao_id": 3,
    "escala_id": 1,
    "ativo": 1
  },
  {
    "id": 11,
    "nome": "Maria Souza",
    "cpf": "555.666.777-88",
    "matricula": "FUNC002",
    "cargo": "Caixa",
    "foto_path": "fotos/func_11.jpg",
    "senha_colaborador": "5678",
    "localizacao_id": 3,
    "escala_id": 1,
    "ativo": 1
  }
]

Possíveis erros

  • 404 – Empresa não encontrada ou inativa.
  • 401 – Dispositivo não autorizado (chave_app inválida ou inativa).

6. Endpoints de Batidas & Apuração

POST /batidas/sincronizar

Recebe batidas de ponto do APP, gera/atualiza a apuração do dia e registra logs (imagem/localização).

Body (JSON) – Exemplo

{
  "codigo_empresa": "RP00155",
  "chave_app": "APP-DEVICE-UUID",
  "batidas": [
    {
      "funcionario_id": 10,
      "data": "2025-11-23",
      "hora": "08:00:00",
      "tipo": "entrada",
      "origem": "totem",
      "imagem": "fotos/10-20251123-080000.jpg",
      "localizacao": "-8.41423,-37.05411"
    },
    {
      "funcionario_id": 10,
      "data": "2025-11-23",
      "hora": "12:00:00",
      "tipo": "saida_intervalo",
      "origem": "totem",
      "imagem": "fotos/10-20251123-120000.jpg",
      "localizacao": "-8.41423,-37.05411"
    },
    {
      "funcionario_id": 10,
      "data": "2025-11-23",
      "hora": "13:00:00",
      "tipo": "retorno_intervalo",
      "origem": "totem",
      "imagem": "fotos/10-20251123-130000.jpg",
      "localizacao": "-8.41423,-37.05411"
    },
    {
      "funcionario_id": 10,
      "data": "2025-11-23",
      "hora": "17:00:00",
      "tipo": "saida",
      "origem": "totem",
      "imagem": "fotos/10-20251123-170000.jpg",
      "localizacao": "-8.41423,-37.05411"
    }
  ]
}

Regras

  • No mesmo payload, para cada funcionario_id + data:
    • mínimo 1 batida
    • máximo 4 batidas
  • Somando com as batidas já salvas para aquela data:
    • O total não pode ultrapassar 4; se passar, o grupo é recusado.
  • Cada batida pode trazer:
    • imagem (string) – caminho ou URL da foto
    • localizacao (string) – coordenadas ou texto

Resposta – 200 OK (exemplo)

{
  "sucesso": true,
  "quantidade_processada": 4,
  "apuracoes": [
    {
      "apuracao_id": 123,
      "empresa_id": 1,
      "funcionario_id": 10,
      "data": "2025-11-23",
      "batidas": [
        "08:00:00",
        "12:00:00",
        "13:00:00",
        "17:00:00"
      ],
      "minutos_trabalhados": 480,
      "batida_impar": false,
      "batida_inregular": false,
      "status_apuracao": "apurado",
      "logs": [
        {
          "hora": "08:00:00",
          "imagem": "fotos/10-20251123-080000.jpg",
          "localizacao": "-8.41423,-37.05411"
        },
        {
          "hora": "12:00:00",
          "imagem": "fotos/10-20251123-120000.jpg",
          "localizacao": "-8.41423,-37.05411"
        },
        {
          "hora": "13:00:00",
          "imagem": "fotos/10-20251123-130000.jpg",
          "localizacao": "-8.41423,-37.05411"
        },
        {
          "hora": "17:00:00",
          "imagem": "fotos/10-20251123-170000.jpg",
          "localizacao": "-8.41423,-37.05411"
        }
      ]
    }
  ],
  "erros": []
}

Observação: o campo minutos_trabalhados é calculado em pares de batidas: (1ª–2ª), (3ª–4ª), somando a diferença em minutos entre cada par.

POST /batidas/atualizar

Atualiza a apuração de um dia específico (batidas e logs) para um funcionário.

Body (JSON) – Exemplo

{
  "codigo_empresa": "RP00155",
  "chave_app": "APP-DEVICE-UUID",
  "apuracao_id": 123,
  "funcionario_id": 10,
  "batidas": [
    {
      "hora": "08:05:00",
      "data": "2025-11-23",
      "imagem": "fotos/10-20251123-080500.jpg",
      "localizacao": "-8.41423,-37.05411"
    },
    {
      "hora": "12:02:00",
      "data": "2025-11-23",
      "imagem": "fotos/10-20251123-120200.jpg",
      "localizacao": "-8.41423,-37.05411"
    },
    {
      "hora": "13:10:00",
      "data": "2025-11-23",
      "imagem": "fotos/10-20251123-131000.jpg",
      "localizacao": "-8.41423,-37.05411"
    },
    {
      "hora": "17:01:00",
      "data": "2025-11-23",
      "imagem": "fotos/10-20251123-170100.jpg",
      "localizacao": "-8.41423,-37.05411"
    }
  ]
}

Regras

  • batidas deve conter entre 1 e 4 itens.
  • Cada item precisa de hora (obrigatório) e pode opcionalmente trazer data, imagem e localizacao.
  • Se data for enviada, deve bater com a data da apuração ou a requisição é recusada.
  • A apuração é totalmente substituída pelas novas batidas, e os logs são recriados.

Resposta – 200 OK (exemplo)

{
  "sucesso": true,
  "apuracao": {
    "apuracao_id": 123,
    "empresa_id": 1,
    "funcionario_id": 10,
    "data": "2025-11-23",
    "batidas": [
      "08:05:00",
      "12:02:00",
      "13:10:00",
      "17:01:00"
    ],
    "minutos_trabalhados": 468,
    "batida_impar": false,
    "batida_inregular": false,
    "status_apuracao": "apurado",
    "logs": [
      {
        "hora": "08:05:00",
        "imagem": "fotos/10-20251123-080500.jpg",
        "localizacao": "-8.41423,-37.05411"
      },
      {
        "hora": "12:02:00",
        "imagem": "fotos/10-20251123-120200.jpg",
        "localizacao": "-8.41423,-37.05411"
      },
      {
        "hora": "13:10:00",
        "imagem": "fotos/10-20251123-131000.jpg",
        "localizacao": "-8.41423,-37.05411"
      },
      {
        "hora": "17:01:00",
        "imagem": "fotos/10-20251123-170100.jpg",
        "localizacao": "-8.41423,-37.05411"
      }
    ]
  }
}

Possíveis erros

  • 404 – Empresa não encontrada ou inativa.
  • 401 – Dispositivo não autorizado.
  • 404 – Apuração não encontrada.
  • 403 – Apuração não pertence à empresa ou ao funcionário informado.
  • 422 – Data das batidas não corresponde à data da apuração.

7. Estruturas de Dados (Modelos)

7.1 Apuração de batidas (apuracoes_batidas)

CampoTipoDescrição
idbigintIdentificador da apuração.
empresa_idbigintEmpresa da apuração.
funcionario_idbigintFuncionário da apuração.
datadateDia de referência da apuração.
escala_nomestring (nullable)Texto com o nome da escala (futuro relacionamento).
batidasjsonArray de horários (ex.: ["08:00:00","12:00:00"]).
motivostring (nullable)Motivo textual (justificativa).
status_apuracaostringnao_apurado, apurado ou pendente.
minutos_trabalhadosintTotal de minutos calculados a partir dos pares de batidas.
observacaostring (nullable)Observações gerais do dia.
inclui_espelhoboolIndica se está incluída no espelho.
batida_imparbooltrue se quantidade de batidas for ímpar.
batida_inregularboolUsado para marcar batidas fora da escala (futuro).

7.2 Log de apuração (log_apuracoes)

CampoTipoDescrição
idbigintIdentificador do log.
apuracao_idbigintReferência à apuração (apuracoes_batidas.id).
empresa_idbigintEmpresa.
funcionario_idbigintFuncionário.
datadateData da batida.
horatimeHora da batida.
imagem_pathstringCaminho/URL da imagem capturada.
localizacaostringLocalização textual ou coordenadas.