API de Check-in
Os exemplos abaixo mostram o header no formato de transmissão
Authorization: P2S-SIGN-V1 API_KEY:TIMESTAMP:SIGNATURE. Para calcular a assinatura no seu código, use o helper signedRequest em Autenticação.checkin:write, ela também faz o check-in e o check-out de um colaborador.
Como funciona
- Você obtém uma API Key com o scope
checkin:read(Admin > Integrações > API Keys) - Seu backend consulta o estado de check-in de um ou vários colaboradores (por CPF ou email)
- O SalesOS responde com o último check-in de hoje por colaborador — e, opcionalmente, contagens de engajamento semana/mês
- Opcionalmente, seu backend faz check-in e check-out com uma key que também tenha
checkin:write, repassando a leitura de GPS do celular do colaborador
Autenticação
Todas as requisições exigem uma API Key no headerAuthorization:
Ambientes
- Produção
- Staging
Base URL:
https://api.play2sell.comReferência do Endpoint
action:
Cada colaborador é identificado por CPF (qualquer formato — os dígitos são normalizados) ou email. Quando os dois são enviados, o CPF prevalece.
Action: checkin_status
Último check-in de hoje por colaborador. “Hoje” é calculado no fuso horário da sua empresa (retornado comotimezone / reference_date na resposta) — nunca em UTC.
Schema da requisição
string
obrigatório
Deve ser
"checkin_status"array
obrigatório
Array de referências de colaborador (máx. 500)
string
CPF, qualquer formato (
52998224725 ou 529.982.247-25). Deve conter exatamente 11 dígitos.string
Email — usado apenas quando
cpf não é enviadoExemplo
Campos da resposta
boolean
Se o CPF/email correspondeu a um colaborador da sua empresa. Colaborador desconhecido vem como
found: false — não é erro, e o array mantém a mesma ordem da requisição.boolean
Se o colaborador tem ao menos um check-in não-rejeitado hoje (fuso da empresa).
boolean
true quando o último check-in está ativo/aprovado e o turno ainda não expirou — ou seja, o colaborador está em plantão agora.object
Check-in mais recente de hoje. Omitido quando não há nenhum.
mode é geo (presencial com GPS), home (home office) ou offline. status pode ser active, approved, pending (aguardando aprovação do líder), expired (turno encerrado normalmente) ou checkout.
location traz a leitura de GPS gravada no check-in: lat, lng, accuracy (metros) e, para check-ins feitos por esta API, captured_at (quando o celular leu o GPS). Ausente quando o check-in não teve GPS (home office, checkout).string
Vínculo do colaborador com a sua empresa (
active, inactive, …). Um colaborador pode ser encontrado e estar inativo.Trilha do dia (include_day)
Envie "include_day": true em checkin_status para receber, além do estado atual, como está o dia turno a turno e quando o botão libera de novo. É o que uma tela inicial precisa para desenhar o bloco de check-in sem abrir o módulo do SalesOS.
Os turnos saem uma vez no topo, não repetidos por pessoa. Num lote de 500 colaboradores isso é a diferença entre uma resposta enxuta e uma de megabytes.
Campos
Action: checkin_engagement
Tudo quecheckin_status retorna, mais contagens de engajamento semana/mês por colaborador. Lotes limitados a 100.
string
obrigatório
Deve ser
"checkin_engagement"array
obrigatório
Array de referências de colaborador (máx. 100)
Exemplo
engagement:
checkins— check-ins na semana/mês corrente (fuso da empresa;expiredconta — é o fim normal de um turno)presence_days— dias distintos com ao menos um check-in
Registrando check-ins
Com o scopecheckin:write, seu backend pode fazer o check-in e o check-out de um colaborador — por exemplo, a partir de um botão “Fazer check-in” na sua própria Home. O efeito é o mesmo de um check-in feito no app SalesOS: o colaborador entra na fila de leads, recebe o turno e o horário em que ele termina, ganha pontos, e os webhooks checkin.confirmed / checkin.checked_out disparam.
As actions de escrita tratam um colaborador por requisição, enviado em collaborator (um objeto, não uma lista). Na escrita, “não encontrado” é erro — não existe escrita parcial:
Action: checkin_options
O que a sua tela pode oferecer agora, para mostrar só o botão que vai funcionar. Somente leitura — exigecheckin:read.
location é opcional. Quando enviado, locations volta ordenado pela distância e duty diz se algum local está ao alcance.
unavailable_reason usa os mesmos códigos que um checkin_create devolveria (MODE_DISABLED, TOO_FAR, HOME_OUTSIDE_SHIFT, HOME_SHIFT_NOT_ALLOWED, PRIOR_GEO_REQUIRED, LOCATION_NOT_FOUND). Os rótulos de modos e turnos são configuração da sua empresa — exiba como vierem.
Action: checkin_create
string
obrigatório
duty (plantão presencial, exige location) ou home (home office).object
A leitura de GPS do aparelho, capturada no celular do colaborador e repassada pelo seu backend. Obrigatória para
duty: lat, lng, accuracy (metros) e captured_at (ISO 8601 — quando o celular leu o GPS).string
O local de plantão escolhido pelo colaborador. Opcional — sem ele, o SalesOS escolhe o local mais próximo dentro do raio.
object
Seu app e versão (
app, version). Guardado junto com o check-in para auditoria.location devolve a leitura de GPS que ficou gravada — mesma forma do latest_checkin.location do checkin_status. Ausente quando não foi enviado GPS.
Um check-in novo encerra o check-in ativo anterior do colaborador, exatamente como no app. Ele vale até shift_expires_at — seu app não precisa ficar enviando sinal de vida.
Requisitos da localização
A leitura de GPS chega pelo seu backend, então o SalesOS confere se ela é recente e precisa antes de confiar nela:
Um check-in recusado não grava nada: o colaborador continua exatamente como estava.
Action: checkin_checkout
Encerra o check-in ativo antes do fim do turno. O colaborador sai da fila de leads na hora echeckin.checked_out dispara.
200, com "already_checked_out": true, e nada é gravado — um clique duplo nunca quebra a sua tela.
Novas tentativas e Idempotency-Key
Envie o header Idempotency-Key (8 a 128 caracteres; um UUID serve) em checkin_create e checkin_checkout. Repetir a requisição com a mesma chave em até 24 horas:
- devolve a mesma resposta, com o header
Idempotency-Replayed: true, sem criar nada novo; - com um corpo diferente, responde
409 IDEMPOTENCY_KEY_REUSED; - enquanto a primeira requisição ainda está rodando, responde
409 IDEMPOTENCY_IN_PROGRESS— tente de novo em alguns segundos.
4xx) não consome a chave: depois de corrigir a causa (uma leitura de GPS nova, por exemplo), você pode tentar de novo com a mesma chave.
O timestamp da assinatura vale por 30 segundos, então cada nova tentativa precisa ser assinada de novo — é a
Idempotency-Key que liga as tentativas.Mensagens para o corretor
Os erros de escrita trazem umamessage em português, escrita para ser exibida direto ao corretor (por exemplo: “Você está a 180 m de Plantão Morumbi. Chegue a até 100 m para fazer o check-in.”). Decida a lógica pelo code, nunca pelo texto.
Modo self (token do usuário do SSO)
Se o seu app já possui o token de um usuário que entrou pelo SSO, o mesmo endpoint responde pelo próprio usuário do token, sem API key:- A identidade vem exclusivamente do token verificado — não envie
collaborators. Requisição com esse campo é rejeitada comSELF_MODE_NO_COLLABORATORS: token de usuário nunca consulta outras pessoas. - O escopo de empresa vem da sessão; a resposta tem exatamente o mesmo formato, com um único item em
collaborators. checkin_engagementfunciona da mesma forma ({ "action": "checkin_engagement" }).- As actions de escrita e
checkin_optionssão só para parceiros: com token de usuário, respondem400 SELF_MODE_NOT_SUPPORTED. Dentro do app SalesOS, o check-in é feito pelo próprio app.
Tratamento de Erros
Todos os erros seguem a estrutura compartilhada:400 — VALIDATION_ERROR
400 — VALIDATION_ERROR
Body inválido, lote acima do limite, CPF sem 11 dígitos, ou item sem
cpf nem email. O array details aponta o index do item.401 — camada de autenticação
401 — camada de autenticação
API key ausente, desconhecida ou expirada, ou assinatura não confere. A resposta traz
error como string e códigos como header_missing, api_key_not_found, signature_invalid, timestamp_too_old.403 — scope_insufficient
403 — scope_insufficient
API key válida, mas sem o scope que a action exige (
checkin:read, ou checkin:write para escrita). Quem responde é a camada de autenticação: { "error": "...", "code": "scope_insufficient", "missing_scopes": ["checkin:write"] }.405 — METHOD_NOT_ALLOWED
405 — METHOD_NOT_ALLOWED
Apenas
POST é aceito.429 — RATE_LIMITED
429 — RATE_LIMITED
Escritas demais para o mesmo colaborador (10 em 10 minutos). Aguarde os segundos de
Retry-After e tente de novo. As actions de escrita têm a própria tabela de erros em Registrando check-ins.500 — SERVER_ERROR
500 — SERVER_ERROR
Erro interno. Faça retry com backoff exponencial (2s, 4s, 8s).
Rate Limits
Segurança
- Leitura exige
checkin:read; criar ou encerrar check-in exigecheckin:write— emita keys de escrita só para o backend dono do botão - Todo check-in criado pela API é guardado com a origem, a key que o criou, o seu
cliente a leitura de GPS original, para auditoria - Cada key é limitada a uma única empresa — CPF de outra empresa responde
found: false - Requisições assinadas com HMAC (P2S-SIGN-V1) e logadas para auditoria; documentos nunca são escritos em logs
Próximos passos
Autenticação
Aprenda a criar e gerenciar API Keys
Suporte
Precisa de ajuda? Fale com nosso time

