Authentication
How to authenticate to the MyStocks Partner API — API keys via Authorization or x-api-key header, scoped read-only data keys for client-side use, Firebase-token endpoints, and the mandatory Idempotency-Key for money-movement calls.
Most requests require your API key. The production partner-portal endpoints POST /register,
POST /session, GET /me, POST /upgrade-request, and POST /api-keys/revoke instead authenticate
with a Firebase ID token from the portal session (see Firebase-token endpoints).
The OAuth token endpoint validates client credentials, and the root-level sandbox reset utility uses
the sandbox key. For API-key-authenticated requests, send the key using either method:
Option A — Authorization header (recommended)
Option B — Custom header
Never expose a full key (pk_live_) in client-side code or public repositories. Prefer a backend
proxy or short-lived token for browser and mobile contexts. A data key (pk_data_) is read-only,
but it remains extractable and shares the parent key's quota. Sandbox keys carry no real-money risk;
production full keys control real funds — guard them accordingly.
Data keys — scoped read-only credentials
Try data key endpointA pk_data_ key is a scoped, read-only credential derived from your full key. It cannot trade, move
funds, or access sub-account PII, but exposing it still permits quota exhaustion and unapproved reuse.
Reserve embedded keys for low-stakes public widgets. For production mobile or web apps, prefer proxying market data through
your backend or minting short-lived tokens via POST /oauth/token: an embedded key can be extracted
by anyone, it shares your full key's rate-limit bucket (an abuser can exhaust your quota), and since
only one data key is active per partner, rotating it breaks every shipped install at once.
Generate a data key via POST /api-keys/data-key (see Key Management).
Data keys share the rate-limit bucket of their parent full key. Any call outside the allowed list
returns 403 FORBIDDEN.
Allowed endpoint families (GET only): /stocks/**, /etfs/**, /bonds/**, /funds/**,
/market/**, the deprecated /market-data/** aliases, /market-intel/**, /opportunities/**,
/dividends/**, /companies/**, and /fx/**. Every other path and every non-GET method returns
403 FORBIDDEN for a data key.
Short-lived tokens — OAuth client credentials
Try OAuth token endpointFor client-side surfaces where you don't want to embed a long-lived key, exchange your key for a
short-lived bearer token via POST /api/v1/partner/oauth/token — a standard OAuth 2.0
client-credentials grant. The token inherits your key's type (full or data) and scopes, expires in
15 minutes, and is prefixed ms_oauth_. This keeps a leaked credential useful for minutes rather
than indefinitely, and lets you rotate without breaking shipped installs.
This grant must be enabled for your partner account first (oauthClientCredentialsEnabled). Until it
is, the endpoint returns 403 — contact us to switch it on.
Send your client_secret (your API key) via HTTP Basic auth, or in a form / JSON body. An optional
scope narrows the token to a subset of your key's scopes:
Use the returned token exactly like a key: Authorization: Bearer ms_oauth_…. When it expires, request
a new one. The token endpoint is rate-limited per source IP to deter credential stuffing.
Firebase-token endpoints
Five production portal operations authenticate with a Firebase ID token
(Authorization: Bearer <firebase-id-token>) rather than a partner API key: POST /register (issues
and rotates a key), POST /session (mints a short-lived portal API token), GET /me (powers the
dashboard UI), POST /upgrade-request (requests production access), and POST /api-keys/revoke
(revokes a supplied compromised key). Their sandbox counterparts can differ: for example,
POST /api/sandbox/v1/reset and sandbox key-management operations authenticate with the sandbox key.
Idempotency — safe retries for authenticated mutations
Try an idempotent depositOn unstable mobile networks a POST can succeed on the server but time out on the client — causing a
double-charge if the app retries. Every authenticated POST, PATCH, PUT, and DELETE request
requires a unique Idempotency-Key header. The only exceptions are sandbox register and
reset, partner apply, upgrade-request, session, and oauth/token. Calls that omit the header are
rejected with 400 MISSING_IDEMPOTENCY_KEY. Keys must contain 8 to 200 characters. We deduplicate by key for 24 hours and return the
cached response on retry.
Use any unique string — a UUID or your own transaction ID works well. If a concurrent duplicate is detected you receive HTTP 409 until the first request completes.
When is it safe to retry?
| Call type | Safe to retry? | How |
|---|---|---|
GET (all read endpoints) | Always | Retry freely with exponential backoff. Reads have no side effects. |
Authenticated POST, PATCH, PUT, or DELETE | Only with Idempotency-Key | Required except for apply, upgrade-request, session, and oauth/token. Resend the exact request with the same key to get the original response back. |
Sandbox POST /register and POST /reset | Yes | Explicitly exempt from the idempotency-header requirement. |
On 429, wait for Retry-After before retrying (see Rate Limits). On
5xx for an authenticated mutation, always retry with the same Idempotency-Key — never generate a
fresh key for a retry of the same logical operation. Generate a new key only for a new logical action.
Was this page useful?
Your signal helps us tighten partner onboarding docs.
Last updated on