API Conventions
Every SalesOS API follows the rules on this page. Read it once and the individual endpoint pages become short: they only tell you what is specific to them.This page is the contract we hold ourselves to. Where an endpoint departs from it, that endpoint’s page says so explicitly — a silent exception is a bug, and we want to hear about it.
Base URLs
- Production
- Staging
https://api.play2sell.com/functions/v1/<name>. There is no /v1/... REST surface — if you find a page describing one, it is out of date; please tell us.
Authentication
Two schemes, and they are disjoint — an endpoint accepts one or the other, never both for the same caller.Partner (server-to-server)
{api_key_id}.{timestamp}.{raw_body}. See Authentication for the signedRequest helper.
- Timestamps older than 300 seconds are rejected (replay protection)
- Sign the raw body bytes, before any re-serialization
- Each key is scoped to a single company; a document from another company answers
found: false
Self mode (federated session)
Error shapes
Requests fail in two different layers, and they answer differently. Handle both — this is the single most common integration bug we see.Authentication layer
Before your request reaches the endpoint’s own logic:error is a string. Common codes: header_missing, header_malformed, invalid_key, signature_mismatch, timestamp_expired.
Endpoint layer
Once authentication passed:error is an object. details points at the offending item by index when the request carried a list.
Payments
The Payments API answers with RFC 7807problem+json instead:
instance is the request id — quote it when opening a ticket.
Status codes
Batching and identity
Partner endpoints take acollaborators array and answer in the same order, one entry per request item.
Identity resolution
Precedence isuser_id > cpf > email. When more than one is sent, the first present wins — the others are ignored, not used as a fallback.
- CPF is accepted in any format; digits are normalized. It must contain exactly 11 digits.
- Unknown person answers
"found": false. That is not an error, and it keeps the array aligned with your request. "ambiguous": trueappears when more than one person matched — treat it as unresolved.
Limits
Batch limits are per action and stated on each page, because they follow the payload each action produces. As a rule: a status action allows 500, an action that expands a list per person allows 100 or fewer.Shared data — campaign metadata, the tenant’s shifts — comes back once at the top of the response, not repeated per person. On a 500-person batch that is the difference between a lean response and a multi-megabyte one.
Configuration belongs to the company, never to your code
This is the rule that most often breaks integrations months after they ship. Names, labels, counts, thresholds and currencies are configured per company and returned in the response. They are not constants.Timezones and dates
Every “today” is computed in the company’s timezone, never UTC. The response states which one it used:timezone from the same response — not the device’s.
Rate limits
Configurable per key, defaulting to 1000 requests/hour. On429, the response carries retry_after in seconds. Back off; do not spin.
Versioning
Contracts are extended, not broken. We may add fields to a response at any time, so parse permissively and ignore what you do not know. New behavior that changes an existing payload ships opt-in, behind a request flag (for exampleinclude_day). Omitting the flag keeps the response you already handle.
Security
- Partner APIs are read-only unless the page says otherwise — they never redeem, never change balances, never accept terms
- Requests are HMAC-signed and logged for audit; documents and emails are never written to logs
- Never call these APIs from client-side code: the key would be exposed
Next steps
Authentication
Create keys and sign requests
Check-in API
Duty presence and the day’s shift track
Missions API
Progress, points earned and points available
Campaigns API
Reward catalog and spendable balance

