SalesOS

Authentication

Authenticate with the SalesOS API using API keys, OAuth 2.0 access tokens or a user session.

Every endpoint except a few public ones (the OpenAPI document, the event catalog, the marketplace catalog, OAuth endpoints) needs a credential. A request without one returns 401.

API keys

API keys are for integrations and automated systems. Create one under Settings → API Keys; the secret is shown once and SalesOS stores only a hash of it.

curl https://api.salesos.org/v1/leads \
  -H "X-API-Key: $SALESOS_API_KEY"

Authorization: ApiKey <key> also works. A key acts as the user who created it, in the organization it was created in, and never has more access than that user. Access is granted per resource with scopes such as READ_LEADS and WRITE_CONTACTS. API-key requests need no CSRF token.

Scopes, expiry, rotation with overlap, IP allow-lists and the routes keys can never reach are in Developers → Authentication.

OAuth 2.0

Apps that act on behalf of other SalesOS users or organizations use OAuth 2.0 (authorization code with PKCE, refresh tokens, client credentials). See Developers → OAuth 2.0.

User sessions

The SalesOS web app signs in with email and password:

Sign in
curl -X POST https://api.salesos.org/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "[email protected]", "password": "your-password" }'
Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIs…",
  "csrf_token": "…",
  "twoFactor": { "requirement": "NONE", "enrollmentDeadline": null },
  "user": { "id": "clx…", "email": "[email protected]", "name": "Jane Smith", "role": "USER" }
}
  • The session token is valid for 1 hour. POST /v1/auth/refresh with the current token returns a new access_token, expires_in and csrf_token.
  • Writes made with a session token must send X-CSRF-Token with the token from the latest login or refresh.
  • POST /v1/auth/logout ends the session.

Sessions are meant for the web app and for the few routes that refuse API keys and OAuth tokens (for example OAuth app management and developer orgs). For integrations, use an API key or OAuth.

Two-factor authentication

When twoFactor.requirement is CHALLENGE, the login returns a limited session. Exchange it for a full one by verifying a TOTP or backup code:

Complete a 2FA sign-in
curl -X POST https://api.salesos.org/v1/auth/2fa/challenge \
  -H "Authorization: Bearer <limited-token>" \
  -H "Content-Type: application/json" \
  -d '{ "code": "123456" }'

The response carries the verified session (access_token) and a new X-CSRF-Token header. ENROLL means the organization requires 2FA and the user has to set it up first (POST /v1/auth/2fa/setup, then POST /v1/auth/2fa/verify-setup with a code).

Organization context

The organization comes from the credential: an API key or OAuth token always acts in the organization it belongs to, and X-Organization-ID can't move it. A session token for a user with several memberships may send X-Organization-ID to choose one.

Security best practices

  • Keep keys and tokens on the server; never ship them in client-side code.
  • Grant the narrowest scopes, set an expiry, and rotate keys with an overlap.
  • Restrict long-lived keys to your integration's IP addresses.
  • Turn on 2FA for every account.

On this page