Fechamento é o marco que separa “dados em revisão” de “dados
definitivos”. Sua integração deve respeitar esse marco para evitar
divergência entre Pontua e sistemas downstream (folha, BI, contabilidade).
Este guia mostra os padrões mais comuns para lidar com fechamento.
Cenário 1 — Sync só após fechamento
Use quando a integração não precisa de dados em tempo real e prioriza
consistência (ex.: alimenta sistema de folha externa).
async function syncSeFechado(token, mes) {
const headers = { Authorization: `Bearer ${token}` }
// 1. Verifica fechamento do mês
const { resultados } = await fetch(
`https://api.pontua.com.br/fechamentos?` +
`dataInicio=${mes}-01&dataFim=${mes}-31&limite=10`,
{ headers },
).then((r) => r.json())
const fechamento = resultados.find((f) => f.status === 'CONCLUIDO')
if (!fechamento) {
console.log(`Mês ${mes} ainda não fechado — pulando sync.`)
return null
}
// 2. Fechado — pode sync com confiança
console.log(`Mês ${mes} fechado em ${fechamento.dataConclusao}, sync OK.`)
return await sincronizarDadosDoMes(token, mes)
}
Use quando você tem um job que processa vários meses ao longo do
tempo. Evita reprocessar meses fechados que já sincronizou.
async function syncIncrementalComCursor(token) {
const ultimoFechamentoSincronizado = await storage.get('pontua.ultimo_fechamento_sync')
// 1. Listar fechamentos concluídos depois do último sync
const params = new URLSearchParams({
status: 'CONCLUIDO',
dataInicio: ultimoFechamentoSincronizado || '2026-01-01',
limite: '100',
})
const { resultados } = await fetch(
`https://api.pontua.com.br/fechamentos?${params}`,
{ headers: { Authorization: `Bearer ${token}` } },
).then((r) => r.json())
// 2. Processar em ordem cronológica
const ordenados = resultados.sort((a, b) =>
a.dataInicio.localeCompare(b.dataInicio)
)
for (const fechamento of ordenados) {
console.log(`Sync ${fechamento.dataInicio} a ${fechamento.dataFim}`)
await sincronizarDadosDoFechamento(token, fechamento)
await storage.set('pontua.ultimo_fechamento_sync', fechamento.dataConclusao)
}
}
Cenário 3 — Reabrir fechamento para correção
Caso raro mas inevitável: descobriu-se erro após fechamento.
Reabrir fechamento é evento auditável. Em fiscalização, reaberturas
frequentes podem ser questionadas pelo MTE. Use com parcimônia e sempre
documente o motivo.
async function reabrirFechamentoComMotivo(token, fechamentoId, motivo) {
// 1. Reabrir
await fetch(
`https://api.pontua.com.br/fechamentos/cancelar/${fechamentoId}`,
{
method: 'PATCH',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
motivo, // string descrevendo a razão
}),
},
)
// 2. Aplicar correção (ajuste, registro, etc.)
// ...
// 3. Re-fechar
await fetch(
`https://api.pontua.com.br/fechamentos/concluir/${fechamentoId}`,
{
method: 'PATCH',
headers: { Authorization: `Bearer ${token}` },
},
)
// 4. CRÍTICO: invalidar exports de folha já enviados
// Notifica seu sistema downstream que o mês precisa re-importar
await meuSistemaFolha.invalidarMes(fechamentoId)
}
Cenário 4 — Fluxo de ajuste em período fechado
Não reabra para cada ajuste — use o fluxo formal de Ajustes.
async function ajustarRetroativo(token, colaboradorId, dataHora, motivoId) {
// 1. Solicitar ajuste (não cria registro direto)
const solicitacao = await fetch(
'https://api.pontua.com.br/ajuste-registro/solicitar',
{
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
colaboradorId,
dataHora,
motivoId,
observacao: 'Correção retroativa via integração',
}),
},
)
const { id: ajusteId } = await solicitacao.json()
// 2. Pode ser aprovado por gestor pelo dashboard ou via API
// (workflow depende do design da empresa)
// PATCH /ajuste-registro/status com status: APROVADO
// 3. Após aprovação, registro é criado e frequência recalculada
// automaticamente. Sem precisar reabrir fechamento.
return ajusteId
}
Verificar antes de cada operação sensível
Padrão defensivo: sempre verifique fechamento antes de operações que
mudam dados:
async function validarSeAberto(token, data) {
const { resultados } = await fetch(
`https://api.pontua.com.br/fechamentos?` +
`dataInicio=${data}&dataFim=${data}&limite=1`,
{ headers: { Authorization: `Bearer ${token}` } },
).then((r) => r.json())
const fechado = resultados.some((f) => f.status === 'CONCLUIDO')
if (fechado) {
throw new Error(
`Data ${data} está em fechamento concluído. ` +
`Use fluxo de ajuste em vez de modificação direta.`
)
}
}
// Uso
await validarSeAberto(token, '2026-04-15')
await fetch('https://api.pontua.com.br/registro-ponto', { /* ... */ })
Notificações ao seu time
Considere alertar Slack/Email quando:
- Fechamento foi concluído → tempo de exportar folha
- Fechamento foi reaberto → invalidar exports já feitos
- Mês passou data limite sem fechamento → cobrar RH
// Polling diário das 9h
async function alertasFechamento(token) {
const hoje = new Date().toISOString().slice(0, 10)
const mesAnterior = new Date(Date.now() - 30 * 86400000)
.toISOString().slice(0, 7)
const { resultados } = await fetch(
`https://api.pontua.com.br/fechamentos?` +
`dataInicio=${mesAnterior}-01&limite=10`,
{ headers: { Authorization: `Bearer ${token}` } },
).then((r) => r.json())
const ultimo = resultados[0]
if (!ultimo || ultimo.status === 'PROCESSANDO') {
await slack.alert(`⚠️ Mês ${mesAnterior} ainda não fechado!`)
}
}
Veja também