Skip to content
MyStocks Developers
API v1

API v1

Current stable contract

Versioning policyRelease changelog
Sandbox console
Start building

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)

# Sandbox
Authorization: Bearer sk_sandbox_<your_key>
 
# Production
Authorization: Bearer pk_live_<your_key>

Option B — Custom header

x-api-key: sk_sandbox_<your_key>  # or pk_live_<your_key>

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 endpoint

A 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 endpoint

For 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:

POST /api/v1/partner/oauth/token
Content-Type: application/x-www-form-urlencoded
 
grant_type=client_credentials&client_id=<your_key_id>&client_secret=pk_live_<your_key>&scope=market:read
{
  "access_token": "ms_oauth_…",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "market:read"
}

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 deposit

On 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.

POST /api/v1/partner/users/{userId}/deposit
Authorization: Bearer pk_live_<your_key>
Idempotency-Key: dep_riven_user_42_1743152580   # unique per attempt

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 typeSafe to retry?How
GET (all read endpoints)AlwaysRetry freely with exponential backoff. Reads have no side effects.
Authenticated POST, PATCH, PUT, or DELETEOnly with Idempotency-KeyRequired 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 /resetYesExplicitly 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.

Send note

Last updated on

On this page