Check-in API
Examples below show the wire-format
Authorization: P2S-SIGN-V1 API_KEY:TIMESTAMP:SIGNATURE header. To compute the signature in your code, use the signedRequest helper in Authentication.checkin:write scope it can also check a collaborator in and out.
How It Works
- You get an API Key with the
checkin:readscope (Admin > Integrations > API Keys) - Your backend asks for the check-in state of one or many collaborators (by CPF or email)
- SalesOS answers with today’s latest check-in per collaborator — plus optional week/month engagement counts
- Optionally, your backend checks people in and out with a key that also has
checkin:write, relaying the GPS reading from the collaborator’s phone
Authentication
All requests require an API Key in theAuthorization header:
Environments
- Production
- Staging
Base URL:
https://api.play2sell.comEndpoint Reference
action field:
Each collaborator is identified by CPF (any format — digits are normalized) or email. When both are sent, CPF wins.
Action: checkin_status
Today’s latest check-in per collaborator. “Today” is computed in your company’s timezone (returned astimezone / reference_date in the response) — never UTC.
Request Schema
string
required
Must be
"checkin_status"array
required
Array of collaborator references (max 500)
string
CPF, any format (
52998224725 or 529.982.247-25). Must contain exactly 11 digits.string
Email — used only when
cpf is absentExample
Response fields explained
boolean
Whether the CPF/email matched a collaborator in your company. An unknown collaborator is
found: false — it is not an error, and the array keeps the same order as your request.boolean
Whether the collaborator has at least one non-rejected check-in today (company timezone).
boolean
true when the latest check-in is active/approved and its shift has not expired — i.e. the collaborator is on duty right now.object
Today’s most recent check-in. Omitted when there is none.
mode is geo (in-person with GPS), home (home office) or offline. status may be active, approved, pending (awaiting leader approval), expired (shift ended normally) or checkout.
location has the GPS reading stored with the check-in: lat, lng, accuracy (meters) and, for check-ins made through this API, captured_at (when the phone read the GPS). Absent when the check-in had no GPS (home office, checkout).string
The collaborator’s membership in your company (
active, inactive, …). A collaborator can be found and inactive.Day track (include_day)
Send "include_day": true on checkin_status to get, beyond the current state, how the day is going shift by shift and when the button unlocks again. This is what a home screen needs to render the check-in block without opening the SalesOS module.
Shifts come back once at the top, not repeated per person. On a 500-collaborator batch that is the difference between a lean response and a multi-megabyte one.
Fields
Action: checkin_engagement
Everythingcheckin_status returns, plus week/month engagement counts per collaborator. Batches are capped at 100.
string
required
Must be
"checkin_engagement"array
required
Array of collaborator references (max 100)
Example
engagement object:
checkins— check-ins in the current week/month (company timezone;expiredcounts — it is the normal end of a shift)presence_days— distinct days with at least one check-in
Writing check-ins
With thecheckin:write scope, your backend can check a collaborator in and out — for example from a “Check in” button on your own home screen. The effect is the same as a check-in made in the SalesOS app: the collaborator enters the lead queue, gets the shift and its end time, earns points, and the checkin.confirmed / checkin.checked_out webhooks fire.
Write actions handle one collaborator per request, sent as collaborator (an object, not a list). In a write, “not found” is an error — there is no partial write:
Action: checkin_options
What your screen can offer right now, so it only shows the button that will work. Read-only — requirescheckin:read.
location is optional. When sent, locations come back sorted by distance and duty says whether any is within reach.
unavailable_reason uses the same codes a checkin_create would return (MODE_DISABLED, TOO_FAR, HOME_OUTSIDE_SHIFT, HOME_SHIFT_NOT_ALLOWED, PRIOR_GEO_REQUIRED, LOCATION_NOT_FOUND). Mode and shift labels are your company’s configuration — render them as they come.
Action: checkin_create
string
required
duty (on-site, requires location) or home (home office).object
The device’s GPS reading, captured on the collaborator’s phone and relayed by your backend. Required for
duty: lat, lng, accuracy (meters) and captured_at (ISO 8601 — when the phone read the GPS).string
The on-site location the collaborator chose. Optional — without it, SalesOS picks the nearest location within its radius.
object
Your app and version (
app, version). Stored with the check-in for audit.location echoes the GPS reading that was stored — same shape as latest_checkin.location in checkin_status. Absent when no GPS was sent.
A new check-in closes the collaborator’s previous active one, exactly as in the app. It stays valid until shift_expires_at — your app does not need to keep pinging.
Location requirements
The GPS reading comes from your backend, so SalesOS checks that it is recent and precise before trusting it:
A refused check-in writes nothing: the collaborator stays exactly as before.
Action: checkin_checkout
Ends the active check-in before the shift ends. The collaborator leaves the lead queue immediately andcheckin.checked_out fires.
200 with "already_checked_out": true and nothing is written — a double tap never breaks your screen.
Retries and Idempotency-Key
Send an Idempotency-Key header (8–128 characters; a UUID works) on checkin_create and checkin_checkout. Repeating the request with the same key within 24 hours:
- returns the same response, with the header
Idempotency-Replayed: true, and creates nothing new; - with a different body, answers
409 IDEMPOTENCY_KEY_REUSED; - while the first request is still running, answers
409 IDEMPOTENCY_IN_PROGRESS— retry in a few seconds.
4xx) does not consume the key: after fixing the cause (a fresh GPS reading, for example) you can retry with the same key.
The signature timestamp is valid for 30 seconds, so a retry must be signed again — the
Idempotency-Key is what ties the attempts together.Messages for the collaborator
Write errors carry amessage in Brazilian Portuguese, written to be shown directly to the collaborator (for example: “Você está a 180 m de Plantão Morumbi. Chegue a até 100 m para fazer o check-in.”). Branch your logic on code, never on the text.
Self mode (SSO user token)
If your app already holds the token of a user who signed in through SSO, the same endpoint answers for the token’s own user, with no API key:- Identity comes only from the verified token — do not send
collaborators. A request with that field is rejected withSELF_MODE_NO_COLLABORATORS: user-level tokens can never look other people up. - The company scope comes from the session; the response has the exact same shape, with a single item in
collaborators. checkin_engagementworks the same way ({ "action": "checkin_engagement" }).- Write actions and
checkin_optionsare partner-only: with a user token they answer400 SELF_MODE_NOT_SUPPORTED. Inside the SalesOS app, check-in is done by the app itself.
Error Handling
All errors follow the shared structure:400 — VALIDATION_ERROR
400 — VALIDATION_ERROR
Invalid body, batch over the limit, CPF without 11 digits, or an item with neither
cpf nor email. The details array points to the item index.401 — authentication layer
401 — authentication layer
API key missing, unknown or expired, or the signature does not match. Answered with
error as a string and codes such as header_missing, api_key_not_found, signature_invalid, timestamp_too_old.403 — scope_insufficient
403 — scope_insufficient
API key is valid but lacks the scope the action needs (
checkin:read, or checkin:write for writes). Answered by the authentication layer: { "error": "...", "code": "scope_insufficient", "missing_scopes": ["checkin:write"] }.405 — METHOD_NOT_ALLOWED
405 — METHOD_NOT_ALLOWED
Only
POST is accepted.429 — RATE_LIMITED
429 — RATE_LIMITED
Too many writes for the same collaborator (10 in 10 minutes). Wait the
Retry-After seconds, then retry. Write actions have their own error table in Writing check-ins.500 — SERVER_ERROR
500 — SERVER_ERROR
Internal server error. Retry with exponential backoff (2s, 4s, 8s).
Rate Limits
Security
- Reading needs
checkin:read; creating or ending check-ins needscheckin:write— issue write keys only to the backend that owns the button - Every check-in created through the API is stored with its origin, the key that created it, your
clientand the raw GPS reading, for audit - Each key is scoped to a single company — a CPF from another company answers
found: false - Requests are HMAC-signed (P2S-SIGN-V1) and logged for audit; documents are never written to logs
Next Steps
Authentication
Learn how to create and manage API Keys
Support
Need help? Contact our support team

