https://app.sideshift.app/api/embed. Every request carries your key in the
x-api-key header, and every response is wrapped in the same envelope.
What you can build
Accounts
One Connect account per user, keyed by your own
externalId. Each account has a SideShift wallet and a withdrawal-ready balance.Transfers
Company to user, user to company, and user to user. Idempotent, with atomic batches of up to 200.
Widgets
Payout and pay-in widgets as iframes, authenticated with short-lived tokens and restyled with URL parameters.
Hosted checkout
A public checkout link or embedded checkout that settles into a SideShift wallet.
Webhooks
Nine signed events covering deposits, transfers, withdrawals and risk flags, with logs, replay and a test endpoint.
Sandbox
sk_test_ keys, isolated wallets seeded with $10,000, provider test cards, and a separate sandbox webhook.How the pieces fit
1
Your backend creates an account
POST /accounts/create with the user’s email and your stable externalId. Store the returned sideshiftAccountId.2
Your backend moves money
POST /accounts/transfer pays the user from your company wallet, or pulls funds back. Each call carries an idempotencyKey so retries are safe.3
Your backend mints a widget token
POST /auth/token returns a short-lived token bound to one domain, plus ready-made widget URLs.4
Your frontend embeds the widget
The payout widget shows the balance, handles identity verification and lets the user withdraw. The pay-in widget lets them add funds.
5
SideShift tells you what happened
Webhooks report deposits, completed transfers and every withdrawal status change, signed with HMAC-SHA256.
Concepts
Accounts
A Connect account is a SideShift user created through your integration. It is identified everywhere bysideshiftAccountId. Send your own user id as externalId when you create
it: SideShift checks externalId before the email, so the same user keeps resolving to the
same account even after they change their email address.
An account is either created by your integration (full access, including transfers
out and widget withdrawals) or merely linked to it (readable and payable, but the
payout widget sends the user to the SideShift app to withdraw).
Where the money sits
A managed account has one balance that matters: its withdrawable balance, held at the payment provider. That is what the payout widget shows, what the user can withdraw, and what auser_to_company transfer pulls back from. GET /accounts/balance reports it as
withdrawableBalanceCents (alias balanceCents).
The account also has an internal SideShift wallet, reported as walletBalanceCents. Money
lands there only when it is paid in through the pay-in widget or an invoice, or when a
transfer is sent with the deprecated destinationBalance: "wallet". Funds in the internal
wallet are not withdrawable until POST /accounts/withdrawal-balance moves them across,
which is why new integrations should leave destinationBalance at its default.
totalBalanceCents is the sum of the two.
Transfer directions
Transfers out of a user account (
user_to_company, user_to_user) are only permitted from
accounts your integration created.
Environments
The key prefix is the whole switch.sk_live_ keys move real money. sk_test_ keys run
against isolated sandbox wallets, a separate sandbox webhook configuration, and the payment
provider’s official sandbox. Paths, bodies, response shapes, validation and error codes are
the same in both. See Testing for exactly what sandbox does and does not
cover.
Conventions
Envelope. A successful response is{ "success": true, "data": … }. A failure is
{ "success": false, "error": { "code", "message", "details"? } }. Account creation returns
201 when it creates and 200 when it reuses an existing account; everything else returns
200 on success.
Amounts are integer cents in USD. amountCents: 5000 is $50.00. Non-integers are
rejected.
Idempotency. Every transfer requires an idempotencyKey of at least 8 characters. Keys
are permanent, scoped to your integration and environment, and replaying one returns the
original result instead of moving money again.
Metadata on transfers is a flat object of string keys and string values: at most 50
keys, keys up to 40 characters, values up to 500 characters. It is stored, returned on
reads, searchable on GET /transfers, and echoed in transfer.completed webhooks.
Rate limits. 100 requests per minute and 100 widget tokens per hour per company, counted
separately for live and sandbox, and 1,000 transfers per UTC day. Details are on
Configuration.
Where to go next
Getting started
Get a key, create an account, mint a token and embed your first widget.
Testing
The sandbox, a complete test plan, and the go-live checklist.
Webhooks
Every event with a full payload, signature verification, retries and replay.
Errors
Every error code, what triggers it, and what to do.
Guides
Escrow, hosted checkout, withdrawal fee markups, white-label domains.
Status
Live component health, 90-day uptime and incidents, as a page and as JSON.
Reference
The generated reference for each operation is in the sidebar under Reference, and the
OpenAPI document is at
app.sideshift.app/openapi/sideshift-connect.yaml.