API de Check-in
Los ejemplos muestran el header en formato de transmisión
Authorization: P2S-SIGN-V1 API_KEY:TIMESTAMP:SIGNATURE. Para calcular la firma en tu código, usa el helper signedRequest en Autenticación.checkin:write, también hace el check-in y el check-out de un colaborador.
Cómo funciona
- Obtienes una API Key con el scope
checkin:read(Admin > Integraciones > API Keys) - Tu backend consulta el estado de check-in de uno o varios colaboradores (por CPF o email)
- SalesOS responde con el último check-in de hoy por colaborador — y, opcionalmente, conteos de engagement semana/mes
- Opcionalmente, tu backend hace check-in y check-out con una key que también tenga
checkin:write, reenviando la lectura de GPS del celular del colaborador
Autenticación
Todas las solicitudes requieren una API Key en el headerAuthorization:
Ambientes
- Producción
- Staging
Base URL:
https://api.play2sell.comReferencia del Endpoint
action:
Cada colaborador se identifica por CPF (cualquier formato — los dígitos se normalizan) o email. Cuando se envían ambos, el CPF prevalece.
Action: checkin_status
Último check-in de hoy por colaborador. “Hoy” se calcula en la zona horaria de tu empresa (devuelta comotimezone / reference_date en la respuesta) — nunca en UTC.
Schema de la solicitud
string
requerido
Debe ser
"checkin_status"array
requerido
Array de referencias de colaborador (máx. 500)
string
CPF, cualquier formato (
52998224725 o 529.982.247-25). Debe contener exactamente 11 dígitos.string
Email — usado solo cuando
cpf no se envíaEjemplo
Campos de la respuesta
boolean
Si el CPF/email correspondió a un colaborador de tu empresa. Un colaborador desconocido viene como
found: false — no es un error, y el array mantiene el mismo orden de la solicitud.boolean
Si el colaborador tiene al menos un check-in no rechazado hoy (zona horaria de la empresa).
boolean
true cuando el último check-in está activo/aprobado y el turno aún no expiró — es decir, el colaborador está de turno ahora.object
Check-in más reciente de hoy. Omitido cuando no hay ninguno.
mode es geo (presencial con GPS), home (home office) u offline. status puede ser active, approved, pending (esperando aprobación del líder), expired (turno finalizado normalmente) o checkout.
location trae la lectura de GPS grabada en el check-in: lat, lng, accuracy (metros) y, para check-ins hechos por esta API, captured_at (cuándo el celular leyó el GPS). Ausente cuando el check-in no tuvo GPS (home office, checkout).string
Vínculo del colaborador con tu empresa (
active, inactive, …). Un colaborador puede ser encontrado y estar inactivo.Recorrido del dia (include_day)
Envie "include_day": true en checkin_status para recibir, ademas del estado actual, como va el dia turno por turno y cuando se habilita el boton de nuevo. Es lo que una pantalla de inicio necesita para componer el bloque de check-in sin abrir el modulo de SalesOS.
Los turnos salen una sola vez arriba, no repetidos por persona. En un lote de 500 colaboradores esa es la diferencia entre una respuesta liviana y una de megabytes.
Campos
Action: checkin_engagement
Todo lo que devuelvecheckin_status, más conteos de engagement semana/mes por colaborador. Lotes limitados a 100.
string
requerido
Debe ser
"checkin_engagement"array
requerido
Array de referencias de colaborador (máx. 100)
Ejemplo
engagement:
checkins— check-ins en la semana/mes corriente (zona horaria de la empresa;expiredcuenta — es el fin normal de un turno)presence_days— días distintos con al menos un check-in
Registrar check-ins
Con el scopecheckin:write, tu backend puede hacer el check-in y el check-out de un colaborador — por ejemplo, desde un botón “Hacer check-in” en tu propia Home. El efecto es el mismo que un check-in hecho en la app SalesOS: el colaborador entra en la fila de leads, recibe el turno y la hora en que termina, gana puntos, y se disparan los webhooks checkin.confirmed / checkin.checked_out.
Las actions de escritura manejan un colaborador por solicitud, enviado en collaborator (un objeto, no una lista). En la escritura, “no encontrado” es un error — no existe escritura parcial:
Action: checkin_options
Lo que tu pantalla puede ofrecer ahora, para mostrar solo el botón que va a funcionar. Solo lectura — requierecheckin:read.
location es opcional. Cuando se envía, locations vuelve ordenado por distancia y duty indica si algún local está al alcance.
unavailable_reason usa los mismos códigos que devolvería un checkin_create (MODE_DISABLED, TOO_FAR, HOME_OUTSIDE_SHIFT, HOME_SHIFT_NOT_ALLOWED, PRIOR_GEO_REQUIRED, LOCATION_NOT_FOUND). Las etiquetas de modos y turnos son configuración de tu empresa — muéstralas tal como llegan.
Action: checkin_create
string
requerido
duty (turno presencial, requiere location) o home (home office).object
La lectura de GPS del dispositivo, capturada en el celular del colaborador y reenviada por tu backend. Obligatoria para
duty: lat, lng, accuracy (metros) y captured_at (ISO 8601 — cuándo el celular leyó el GPS).string
El local de turno que eligió el colaborador. Opcional — sin él, SalesOS elige el local más cercano dentro de su radio.
object
Tu app y versión (
app, version). Se guarda junto con el check-in para auditoría.location devuelve la lectura de GPS que quedó grabada — misma forma que latest_checkin.location de checkin_status. Ausente cuando no se envió GPS.
Un check-in nuevo cierra el check-in activo anterior del colaborador, igual que en la app. Es válido hasta shift_expires_at — tu app no necesita seguir enviando señales de vida.
Requisitos de la ubicación
La lectura de GPS llega por tu backend, así que SalesOS verifica que sea reciente y precisa antes de confiar en ella:
Un check-in rechazado no graba nada: el colaborador queda exactamente como estaba.
Action: checkin_checkout
Cierra el check-in activo antes del fin del turno. El colaborador sale de la fila de leads en el acto y se disparacheckin.checked_out.
200, con "already_checked_out": true, y no se graba nada — un doble toque nunca rompe tu pantalla.
Reintentos e Idempotency-Key
Envía el header Idempotency-Key (8 a 128 caracteres; un UUID sirve) en checkin_create y checkin_checkout. Repetir la solicitud con la misma clave dentro de 24 horas:
- devuelve la misma respuesta, con el header
Idempotency-Replayed: true, sin crear nada nuevo; - con un cuerpo distinto, responde
409 IDEMPOTENCY_KEY_REUSED; - mientras la primera solicitud sigue en curso, responde
409 IDEMPOTENCY_IN_PROGRESS— reintenta en unos segundos.
4xx) no consume la clave: después de corregir la causa (una lectura de GPS nueva, por ejemplo), puedes reintentar con la misma clave.
El timestamp de la firma vale 30 segundos, así que cada reintento debe firmarse de nuevo — la
Idempotency-Key es lo que une los intentos.Mensajes para el colaborador
Los errores de escritura traen unmessage en portugués de Brasil, escrito para mostrarse directamente al colaborador (por ejemplo: “Você está a 180 m de Plantão Morumbi. Chegue a até 100 m para fazer o check-in.”). Decide la lógica por el code, nunca por el texto.
Modo self (token del usuario del SSO)
Si tu app ya posee el token de un usuario que entró por SSO, el mismo endpoint responde por el propio usuario del token, sin API key:- La identidad viene exclusivamente del token verificado — no envíes
collaborators. Una solicitud con ese campo se rechaza conSELF_MODE_NO_COLLABORATORS: un token de usuario nunca consulta a otras personas. - El alcance de empresa viene de la sesión; la respuesta tiene exactamente el mismo formato, con un único ítem en
collaborators. checkin_engagementfunciona de la misma manera ({ "action": "checkin_engagement" }).- Las actions de escritura y
checkin_optionsson solo para socios: con token de usuario responden400 SELF_MODE_NOT_SUPPORTED. Dentro de la app SalesOS, el check-in lo hace la propia app.
Manejo de Errores
Todos los errores siguen la estructura compartida:400 — VALIDATION_ERROR
400 — VALIDATION_ERROR
Body inválido, lote sobre el límite, CPF sin 11 dígitos, o ítem sin
cpf ni email. El array details indica el index del ítem.401 — capa de autenticación
401 — capa de autenticación
API key ausente, desconocida o expirada, o la firma no coincide. La respuesta trae
error como cadena y códigos como header_missing, api_key_not_found, signature_invalid, timestamp_too_old.403 — scope_insufficient
403 — scope_insufficient
API key válida, pero sin el scope que requiere la action (
checkin:read, o checkin:write para escritura). Responde la capa de autenticación: { "error": "...", "code": "scope_insufficient", "missing_scopes": ["checkin:write"] }.405 — METHOD_NOT_ALLOWED
405 — METHOD_NOT_ALLOWED
Solo se acepta
POST.429 — RATE_LIMITED
429 — RATE_LIMITED
Demasiadas escrituras para el mismo colaborador (10 en 10 minutos). Espera los segundos de
Retry-After y reintenta. Las actions de escritura tienen su propia tabla de errores en Registrar check-ins.500 — SERVER_ERROR
500 — SERVER_ERROR
Error interno. Reintenta con backoff exponencial (2s, 4s, 8s).
Rate Limits
Seguridad
- La lectura requiere
checkin:read; crear o cerrar check-ins requierecheckin:write— emite keys de escritura solo para el backend dueño del botón - Todo check-in creado por la API se guarda con su origen, la key que lo creó, tu
clienty la lectura de GPS original, para auditoría - Cada key está limitada a una única empresa — un CPF de otra empresa responde
found: false - Solicitudes firmadas con HMAC (P2S-SIGN-V1) y registradas para auditoría; los documentos nunca se escriben en logs
Próximos pasos
Autenticación
Aprende a crear y gestionar API Keys
Soporte
¿Necesitas ayuda? Habla con nuestro equipo

