X-API-KEY header:
Authorization. That is how an
approved application — SOAR’s MCP server, for one — acts for a user
who never hands over a key. Tokens are issued to registered clients only, so if you
are building your own bot, use an API key.
One route needs no credential at all — the contract itself:
Creating a key
1
Sign in at app.trysoar.com
Keys are issued to your account, so this step happens as you, in the app — not
as a bot. Open Settings → Developer settings.
2
Create a key with the scopes you need
Name it for the thing that will use it. Almost every trading integration wants
both
read and trade:3
Save the key immediately
The raw key is shown once. We store only a hash of it, so losing it means
issuing a new one. We do keep a short prefix so you can tell your keys apart in
a list.
Creating, listing, and revoking keys happens in the app, authenticated by your
session rather than by a key — so no endpoint here can issue its own
successor. Everything a bot does is under
https://api.trysoar.com/v1.Scopes
A key carries an explicit list of scopes. Each route requires exactly one.
Those two are the whole vocabulary for a key, and both are yours to issue.
Bearer tokens carry finer-grained scopes instead, granted per application at consent
time —
soar:markets:read, soar:account:read, soar:orders:write, and
soar:orders:bulk-cancel. Each endpoint in the API Reference names the one
it needs.
A key with an empty scope list is rejected everywhere.
401 versus 403
These are different problems with different fixes, and the distinction is worth coding against.
Whether a
WWW-Authenticate header comes back depends on which credential failed.
A bearer failure carries one, because an OAuth client is expected to act on it: a
401 names the protected-resource metadata URL, and a 403 names the scope that was
missing. An API-key failure carries none — there is no challenge-response step for
a key you already hold, and a browser that receives a challenge pops a native
credential dialog that would break the playground on this site.
See Errors for the full code vocabulary.
Rate limits
One token bucket per credential across the whole API: 250 requests/second sustained, 500 burst. A key gets its own bucket; a bearer token draws on one keyed to the granting application and user. Every response to an authenticated request carriesX-RateLimit-Limit and X-RateLimit-Remaining; a 429 adds Retry-After.
The limit is per credential, not per route — a busy market-data poller and your
order flow draw from the same bucket. Use separate keys if you want them isolated.
Details, and why a throttled cancel is the case to be careful about, are in
Errors.
Handling keys
- Send the key in the
X-API-KEYheader only. Never in a URL or query string — URLs end up in logs, proxies, and browser history. - Revoke a key the moment it is no longer used, and whenever you suspect exposure.
- A leaked
tradekey can move your positions. The venue trades paper money today; that is not a reason to be casual with a credential whose habits you will carry forward.