Skip to main content

Authentication

Try signed requests in your browser at the API Sandbox — paste your API key and secret, and the playground signs requests automatically.
The SalesOS Integration API uses the P2S-SIGN-V1 signed-request scheme in the Authorization header. API Keys are scoped to a single tenant, hashed with bcrypt, and support rate limiting and IP allowlists.

Environments

Base URL: https://api.play2sell.comDashboard: https://dashboard.play2sell.comApp: https://app.play2sell.com

Quick Start

1. Create an API Key

Go to Integrations > API Keys in the SalesOS Dashboard:
  1. Click Create API Key
  2. Name your key (e.g., “CRM Nightly Sync”, “Website Form Integration”)
  3. Select the scope: default:sync
  4. Click Create
  5. Copy both values immediately — they are only shown once:
    • API Key — public identifier, e.g. sk_live_a1b2c3d4...
    • API Key Secret — used to sign requests, never sent over the wire

2. Sign and Send a Request

For server-to-server calls, build the Authorization header as P2S-SIGN-V1 API_KEY:TIMESTAMP:SIGNATURE. The signature is hex HMAC-SHA256 of a 5-step derived-key chain:
  1. k1 = HMAC_SHA256(key=API_KEY_SECRET, msg=API_KEY)
  2. k2 = HMAC_SHA256(key=k1, msg=TIMESTAMP)
  3. k3 = HMAC_SHA256(key=k2, msg=METHOD)
  4. k4 = HMAC_SHA256(key=k3, msg=PATH)
  5. SIG = HMAC_SHA256_HEX(key=k4, msg=PAYLOAD_SHA256_HEX)
TIMESTAMP is Unix epoch seconds, valid for 30 seconds. PAYLOAD_SHA256_HEX is the lowercase hex SHA-256 of the raw request body (use the empty-string digest e3b0c4...b855 if there is no body).
Don’t want to write the signing code yet? The API Sandbox signs requests for you in the browser — paste your API key and secret, then click Try it out.

3. Check the Response

Success (200):
Invalid signature or timestamp outside the window (401):

API Key Properties


Key Formats

SalesOS uses two key prefixes to distinguish environments:
Use sk_test_ keys during development and integration testing. Switch to sk_live_ when you go to production.

Authentication Errors

Every rejection from the authentication layer has the same shape: error is a human-readable string and code is stable — branch on code, never on the text.

Example: Key without required scope

missing_scopes only appears in this case.

Rate Limits

Each API key has an independent rate limit counter that resets hourly: How it works:
  1. Every authenticated and authorized request counts in the key’s window (authentication rejections do not count)
  2. The window is one hour from the first request
  3. Today the limit is measured but not enforced. Once enforcement is on, excess requests will get 429 with code: "rate_limited" and a Retry-After header in seconds — handle it now
Handling rate limits in code:

Security Best Practices

Never expose API keys in client-side code. Browser JavaScript, mobile apps, and public repositories can all leak your key. Always call the SalesOS API from your backend server.
  • Use environment variables — Store SALESOS_API_KEY in env vars or a secrets manager, never in source code
  • Rotate keys periodically — Create a new key, update your integration, then revoke the old one
  • Use IP allowlists — If your integration runs from fixed IPs, restrict the key to those IPs only
  • Monitor usage — Check the API usage logs in the Dashboard for unexpected patterns
  • Use sk_test_ for development — Test keys isolate your dev environment from production
  • Revoke compromised keys immediately — Go to Dashboard > Admin > API Keys > Revoke

Key rotation example


Next Steps

Default Integration

Start sending activities to SalesOS

API Keys

Manage keys programmatically