Skip to main content
Programs, contracts, payouts, analytics, and posts - the core SideShift product surface. The current Platform API supports two scoped authentication methods on the same full read and write surface: a Platform API key for your own company, or OAuth 2.1 when another company grants your app access.
The older Platform API at /api/v1 is legacy and deprecated. It is not maintained and must not be used for new integrations. Existing integrations should migrate to the current Platform API at /api/oauth/v1.

Before you start

What you need
  • A SideShift company account with an active subscription - OAuth protected resource calls return 402 subscription_required without one
  • A backend to call from. Keys and tokens must never reach the browser
What to install Nothing. There is no SDK and no CLI for the Platform API - it’s plain HTTP, so use whatever your language already has.
Searching npm for “sideshift” returns packages belonging to SideShift.ai, an unrelated crypto exchange. None of them work with this API.

Choose how to authenticate

Both choices are tenant-bound and scoped. The difference is who grants access: your company admin creates an API key directly, while another SideShift company authorizes an OAuth app through a consent screen. MCP clients use OAuth.

Platform API key

For your own company, create a key in Settings → Platform API & MCP → API keys and call any resource operation with x-api-key:
The key starts with sspk_live_ or sspk_test_, belongs to one company, and carries only the scopes selected at creation, capped by the creator’s current permissions. A parent agency can also select direct subaccount delegation. Follow the API key quickstart for setup, safe rotation, and copyable examples.

OAuth 2.1

Use OAuth authorization code with PKCE when your integration connects another SideShift company. The steps below summarize the flow; the OAuth quickstart contains the complete, copyable version.
1

Register your application

Send your app name, callback URL, and requested scopes to POST /api/oauth/v1/register. Save the returned client_id and one-time registration_access_token.Start with the narrowest scope you need. For a read-only first request, use campaigns:read.
2

Create PKCE values

Generate a random code_verifier, derive its SHA-256 code_challenge, and create a random state. Keep the verifier and state in the user’s server-side session.
3

Send the user to SideShift

Redirect the browser to GET /api/oauth/v1/authorize with the client_id, a registered callback URL, scopes, state, and PKCE challenge. The callback must match a registered URI exactly, except a native HTTP loopback callback, which may vary only the port. The user signs in, selects a company, and approves the scopes.SideShift returns code, state, and iss to your callback. Verify state and verify that iss is https://app.sideshift.app.
4

Exchange the code

From your backend, send the code, callback URL, client_id, and original code_verifier to POST /api/oauth/v1/token. You receive a one-hour access token and, when your client registered the refresh_token grant, a refresh token.
5

Call the Platform API

Send the access token as a bearer token:
List endpoints return { data, nextCursor, hasMore }. Pass nextCursor back as cursor to fetch the next page.

OAuth endpoint map

Keep the connection active

Access tokens expire after one hour. Refresh tokens rotate on every use: save the new refresh token from each successful refresh response before discarding the previous one. Reusing an old refresh token revokes the token family.

Legacy API (Deprecated)

The API-key surface is retained only for existing integrations while they migrate. It is not maintained, receives no new features or fixes, and is not an alternative setup path for new work. Existing integrations send an older key in x-api-key and use /api/v1. See the Legacy API (Deprecated) reference in the sidebar for its frozen contract. A current sspk_… key is not compatible with /api/v1; an older sk_live_… key is not compatible with /api/oauth/v1.

The practical difference

The current and deprecated surfaces are not the same API with different credentials. The deprecated surface is read-oriented: of its 24 operations, 19 are GET. Only five write anything -
  • POST /posts/export
  • POST /programs/{id}/invite
  • POST /invoices, POST /invoices/{invoiceId}/send, POST /invoices/{invoiceId}/void
So anything that creates a campaign, signs a contract, executes a payout, or sends a message requires the current /api/oauth/v1 surface, authenticated by a scoped Platform API key or OAuth. They also behave differently on the wire - not just different credentials, but different pagination, error shapes, and idempotency rules.
On the legacy API only, agency (parent) accounts can pass scope=agency on the API key’s analytics and posts endpoints to aggregate across the parent agency and every subaccount.

MCP server

The same OAuth-scoped capabilities are exposed through a remote Model Context Protocol server at POST /api/mcp, using the Streamable-HTTP transport. An AI agent can operate a SideShift company through MCP tools instead of raw HTTP calls. Connecting a client. Point any MCP client at https://app.sideshift.app/api/mcp. It authenticates with the same OAuth 2.1 flow above - there is no MCP-specific auth scheme. Tokens minted for MCP are multi-audience, so a single token works for both /api/oauth/v1 and /api/mcp. An unauthorized request gets a 401 with a WWW-Authenticate challenge pointing at the RFC 9728 protected-resource metadata, so compliant clients can auto-discover the authorization server. What you get. Every capability scope maps to tools, mirroring the REST surface plus a whoami tool. Read scopes expose read-only tools. Write and sensitive tools carry a confirmation guardrail in their description. The claim-link capability is available as the create_quickpay_claim_link tool.

Sandbox and sensitive operations

Test and sandbox grants can exercise reads and safe writes, but requests that move money or trigger outbound side-effects - payouts, sending invoices or messages, external re-scrapes - are rejected. Getting a sandbox client. For a human OAuth integration, pass "sandbox": true when you register, then complete the authorization-code flow:
Every token that client is issued then carries a sandbox claim, and the guarded routes refuse it with 403 and payouts:write is not available for sandbox (test-mode) grants. There is no separate sandbox host. The OAuth sandbox flag is set at registration and cannot be changed afterward. For an internal script, the API key dialog offers a Test mode. Public registration does not authorize machine access; use the dashboard for company automations. Two things worth knowing before you rely on it. Only the literal JSON true enables test mode, so "true" or 1 leave the client in production mode; this is deliberate, because the damaging mistake is a real client silently having its payouts refused. And the flag cannot be changed afterwards - register a separate client rather than promoting one out of test mode, since integrations may already depend on its writes being inert. Money-moving endpoints and campaign analytics-history validation/import requests require an Idempotency-Key. Sensitive MCP tools are rejected for sandbox and test grants, and can be disabled globally with the MCP_SAFE_MODE server flag.

Coverage

Campaigns and programs are the same concept; the current spec names them campaigns, the legacy spec names them programs. The current reference spans the full Platform surface and documents both supported authentication methods. The legacy reference remains frozen and narrow.
Platform access requires an active SideShift subscription - protected resource calls from a company without one return 402. Restricted endpoints (Jobs, Applicants, payout execution) are documented in a separate frozen Full Access specification available to allowlisted partner accounts, and are not part of the public legacy reference on this site. A non-allowlisted key calling them receives 403.