Before you start
Connect is off by default. Until SideShift enables it for your company, every call returns403 EMBED_NOT_ENABLED with the message Embed access is not enabled for this company. Contact support to request access. Check this first rather than last.
You also need a payment account on your company before a key can be generated. The
console shows a “Payment account required” prompt in place of the key controls until it
exists.
API keys
Keys live in the Connect console at app.sideshift.app/connect?tab=widgets, under API Keys. There are two independent modes, each with its own Generate button.
A key is the prefix plus 32 characters of base64url, so it can contain
- and _.
SideShift stores a SHA-256 hash and a short preview, which is why a key is shown exactly
once and cannot be recovered. A company can hold several active keys per mode; each has
its own id and name and is revoked independently, so rotation is create, deploy, then
revoke.
Send the key in the x-api-key header on every request, and keep it in an environment
variable rather than in code:
Your first integration
1
Create an account for your user
email is required. name is trimmed to 100 characters and externalId to 200.Send externalId anyway. SideShift checks it before the email, so the same
externalId keeps returning the same account even after the user changes their email
address. Without it, one person with two addresses becomes two separately payable
accounts.You get 201 on creation and 200 when the account already existed, with the same
body either way:"created": false and "alreadyExists": true. If SideShift
had to provision the account under a fallback email, emailModified is true and
originalEmail holds what you sent; see
account fallback emails.Store data.sideshiftAccountId. It is the handle for everything else.2
Allow the domain you will embed on
In the console, add the domains the widget is allowed to load on. A pattern matches
exactly, or as
*.example.com for the base domain and every subdomain.This step is not optional bookkeeping. Every token is bound to one domain when it is
minted. The endpoint picks that domain from targetDomain in the body if you send
one, otherwise from the request’s Origin header, otherwise from the first entry on
your allowlist. A server-side call sends no Origin, so with an empty allowlist there
is nothing to bind to and the next step fails with 400 DOMAIN_NOT_ALLOWED.localhost cannot be added to the list (entries need a dot) and does not need to be:
a widget loaded from localhost, 127.0.0.1, 0.0.0.0 or ::1 passes the domain
check on any port. Add your real domain now and develop on localhost.3
Mint a widget token
sideshiftAccountId and widgetType are required. widgetType is payout, payin
or both.expiresInSeconds defaults to 3600 and accepts 60 to 86400. A value outside that
range is rejected with 400 VALIDATION_ERROR rather than clamped, so range-check it
before sending.widgetUrls only contains the widgets you asked for. If you saved a widget theme in
the console, the URLs already carry it as query parameters; append your own with &.The account has to belong to your integration. An id you did not create or link
comes back as
404 ACCOUNT_NOT_FOUND, not 403. That is deliberate: a 403 would
confirm the account exists, which would turn this endpoint into a way to probe for
accounts on other platforms.4
Embed the widget
Use The
widgetUrls from the response directly as the iframe src.allow attribute matters. Identity verification uses the camera, and card flows
need payment permissions. Without it those steps fail inside the frame.The token sits in the URL path, so anything that logs full URLs logs a live
credential. Keep lifetimes short and mint the token on your backend at the moment you
render the page.5
Pay the user
Move money from your company wallet into the user’s account. In sandbox your company
wallet is seeded with $10,000 on the first authenticated request, so this works
immediately.
idempotencyKey is required and must be at least 8 characters. Sending the same
request again returns this same result instead of paying twice. The metadata block
is the commercial evidence live integrations must attach; it is optional in sandbox.
Full semantics are on Testing and
Configuration.6
Listen for events
Configure a webhook endpoint in the console and verify every delivery’s signature.
The event you will want first is Deliveries are attempted up to three times, one second then two seconds apart, and
are deduplicated by the
transfer.completed.X-Sideshift-Event-Id header. Every event, header and retry
rule is on Webhooks.Where to go next
Testing
What sandbox covers, test cards, and a step-by-step plan through accounts, transfers, widgets, checkout and webhooks.
Embedding and customization
Sizing, overlays, every theme and label parameter, and the events the widget posts back to your page.
Configuration
Keys, allowed domains, limits and the settings that shape an integration.
Errors
Every code the API returns and what to do about it.