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 /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.
/register
Register sandbox account
Full endpoint documentationcreateRegisterCreates a sandbox account and returns a sandbox API key (sk_sandbox_…). Authentication: Pass your Firebase ID token as Authorization: Bearer <token>. The recommended flow is to sign in at the partner dashboard and use its explicit Create/Rotate Key action; the portal performs this authenticated request without exposing the Firebase token. The token identifies your Firebase account and links the sandbox key to your partner profile. - Your master wallet is seeded with a virtual $100,000 on first registration. - Calling this endpoint again rotates the credential and immediately invalidates the previous sandbox key. - The sandbox is fully isolated — no real money moves. To go live, complete KYB verification via the partner dashboard and request a production key.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer Firebase ID token from your partner portal session.
Response fields
messagestringExample: "Sandbox account created."
apiKeystringExample: "sk_sandbox_a1b2c3d4e5f6"
walletBalancenumberExample: 100000
currencystringExample: "USD"
existingbooleantrue if your account already existed and the key was retrieved rather than created.
Example: false
Response codes
201Registration successful.401Missing or invalid Firebase ID token.403No partner application on file. Apply at /partners/register first./session
Mint a portal session token
Full endpoint documentationcreatePartnerSessionExchanges a Firebase ID token (the partner's portal login) for a short-lived ms_oauth_ access token that can be sent as Authorization: Bearer <token> to any partner endpoint. This exists because partner API keys are stored only as SHA-256 hashes: the raw pk_live_ key is displayed once, at issue or rotation, and is unrecoverable afterwards. GET /me can therefore only return a mask. A signed-in portal session uses this endpoint to obtain a credential it can actually call with. The token carries the active organization member and mirrors the underlying key's scopes and type. Effective access is the intersection of member permissions, key scopes, organization security policy, and environment policy. It expires after 1 hour and can be revoked earlier. Server-to-server integrations should keep using their pk_live_ key directly, or the OAuth client-credentials flow (POST /partner/oauth/token) — not this endpoint.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer Firebase ID token from your partner portal session.
Response fields
accessTokenstringSend as Authorization: Bearer <accessToken>. Prefixed ms_oauth_.
tokenTypeBearerexpiresInintegerLifetime in seconds (3600).
keyTypefull | dataMirrors the underlying key. data tokens are read-only market-data credentials.
memberobjectmember.idstringRequiredmember.uidstringmember.emailstringRequiredmember.displayNamestring | nullmember.roleIdsstring[]Requiredmember.permissionsstring[]Requiredmember.statusINVITED | ACTIVE | SUSPENDED | REMOVEDRequiredmember.activeSessionCountintegerpermissionsstring[]sessionIdstringResponse codes
200A short-lived partner access token.401Missing or invalid Firebase ID token.403No partner key provisioned for this account, or the key is suspended/revoked./me
My status and workspace access
Full endpoint documentationlistMeReturns the current partner account status. The production-only workspace=1 variant requires verified email and returns deploymentPreference, hosted approval and nextAction, sandbox status, installations (at most 50), limit and environment eligibility. Summary contains no raw installation secrets. Installation evaluation is Sandbox-only; Hosted approval and installation licensing are independent. Legacy organizations without an explicit Hosted decision retain their existing grant checks. Authentication: This endpoint requires a Firebase ID token (Authorization: Bearer <firebase-token>), not a partner API key. It is used by the partner portal dashboard on login. Response varies by account state: - Active live key → returns status: active, maskedKey, businessName, email maskedKey is for display only — it is not a usable credential. API keys are stored as SHA-256 hashes, so the raw key is shown exactly once (at issue or rotation) and cannot be retrieved afterwards. To call the API from a signed-in portal session, exchange the Firebase ID token for a short-lived access token via POST /api/v1/partner/session. - Suspended key → returns status: suspended, businessName - Pending/rejected application (no live key yet) → returns status, businessName, applicationSubmittedAt, applicationRejectionReason - No application → returns status: not_found
Parameters
workspace1queryUse 1 for the verified-email workspace summary instead of the legacy status response.
Headers
AuthorizationstringRequiredBearer Firebase ID token from your partner portal session.
Response fields
deploymentPreferencehosted | onprem | bothPresent in workspace=1 summaries; preference does not grant authority.
hostedobjecthosted.statusstringhosted.liveAllowedbooleanhosted.codestring | nullhosted.nextActionstringhosted.keyLast4string | nullsandboxobjectsandbox.statusstringsandbox.nextActionstringenvironmentobjectenvironment.liveAllowedbooleanenvironment.statusstringlimitintegerinstallationsobject[]installations[].idstringinstallations[].requestIdstring | nullinstallations[].domainstring | nullinstallations[].statusstringinstallations[].domainVerificationstringinstallations[].licenseStatusstringinstallations[].accessLevelstringinstallations[].accessTypestring | nullinstallations[].expiresAtstring | nullinstallations[].keyLast4string | nullinstallations[].installationStatestringinstallations[].identityStatusstringinstallations[].retrievalStatestringinstallations[].nextActionstringstatusactive | suspended | pending | approved | rejected | sandbox_active | not_foundsandboxActivebooleanTrue when this Firebase user has an active isolated sandbox identity.
maskedKeystringDisplay-only mask of the partner's live key (e.g. pk_live_a1b2c3d4...9f2e). Present when status is active. NOT a usable credential — sending it as a Bearer token returns 401. Use POST /api/v1/partner/session for a credential the portal can actually call with.
businessNamestring | nullemailstring | nullapplicationSubmittedAtstring | nullWhen the partner application was submitted. Present for pending/approved/rejected states.
applicationRejectionReasonstring | nullAdmin-provided rejection reason. Present when status is rejected.
Response codes
200Legacy partner account status, or workspace summary when workspace=1. Additional workspace fields are described above.401Missing or invalid Firebase identity token.403Email unverified, inactive membership or installation authorization denied.500Admin service unavailable./me
Select a portal environment or save deployment preference
Full endpoint documentationupdatePartnerWorkspaceVerified-email Firebase portal operation. Rechecks workspace and installation authorization. select_environment returns a fixed navigation path only; it never grants approval or issues credentials. deployment_preference saves a personal preference and audit event, never organizational authority. This endpoint does not use the integration Idempotency-Key mechanism.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer Firebase ID token from your partner portal session.
Response fields
See the response format and API Reference for this endpoint.
Response codes
200Validated navigation or saved personal preference; no credential issuance.400Invalid action, environment, preference or body.401Workspace authentication failed.403Verified sign-in, membership, Hosted or installation authority missing.500Workspace Admin service unavailable.503Admin service unavailable before workspace resolution./upgrade-request
Submit upgrade request
Full endpoint documentationcreateUpgradeRequestSubmits an upgrade request to the MyStocks partnerships team. Authentication: Firebase ID token required (Authorization: Bearer <firebase-token>). Two modes: - Sandbox → live key (default, no targetTier): for partners without a live key yet. Triggers KYB review; live pk_live_ key issued within 1–2 business days. - Tier upgrade (targetTier required): for partners with an active live key who want to move from starter → growth or enterprise.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer Firebase ID token from your partner portal session.
Request body
messagestringOptional message to the reviewing team.
targetTiergrowth | enterpriseRequired for tier upgrade requests. Omit for sandbox-to-live requests.
Response fields
messagestringrequestIdstringResponse codes
201Request submitted.400Invalid targetTier or already on that tier./api-keys/revoke
Revoke API key
Full endpoint documentationcreateRevokePermanently revokes a specific API key. Use this to invalidate a compromised key immediately. If you revoke your only active key, you must contact support to restore access.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer Firebase ID token from your partner portal session.
Idempotency-KeystringheaderRequiredUnique string that makes write calls safe to retry on network failure. Required for money movement, trading, KYC, subscriptions, and webhook creation. Deduplicated for 24 hours -- duplicate keys return the cached response. HTTP 409 if a concurrent request with the same key is still in progress.
Example: dep_user42_1743152580
Request body
apiKeystringRequiredThe pk_live_ key to permanently revoke. Must belong to your account.
Example: "pk_live_a1b2c3d4e5f6..."
Response fields
messagestringExample: "API key revoked."
apiKeystringMasked form of the revoked credential.
Response codes
200Key revoked.404Key not found or does not belong to this account.Data keys — scoped read-only credentials
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.
/oauth/token
Issue OAuth client-credentials access token
Full endpoint documentationcreateOAuthTokenIssues a short-lived Bearer token for partners that have OAuth client credentials enabled in their enterprise security policy. Provide the partner API key as the client secret via HTTP Basic auth, form body, or JSON body.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Request body
grant_typeclient_credentialsclient_idstringOptional partner client identifier. Defaults to the authenticated key document id.
client_secretstringRequiredPartner API key used as the client secret.
scopestringSpace-delimited scopes requested for the short-lived access token.
Example: "trading:write reports:read"
Response fields
access_tokenstringExample: "ms_oauth_..."
token_typestringExample: "Bearer"
expires_inintegerExample: 900
scopestringResponse codes
200Short-lived OAuth access token.403OAuth client credentials are not enabled for this partner./api-keys/data-key
Issue data API key
Full endpoint documentationcreateDataKeyIssues a new read-only data API key. Only one data key can be active at a time — calling this again rotates the existing key. ⚠️ Prefer server-side use. An embedded pk_data_ key can be extracted from any client bundle, shares the parent full key's rate-limit bucket, and rotating it (or calling this endpoint again) breaks every shipped install (only one is active per partner). For production apps, proxy market data through your backend or use short-lived tokens from POST /oauth/token; reserve embedded data keys for low-stakes surfaces such as public widgets.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Idempotency-KeystringheaderRequiredUnique string that makes write calls safe to retry on network failure. Required for money movement, trading, KYC, subscriptions, and webhook creation. Deduplicated for 24 hours -- duplicate keys return the cached response. HTTP 409 if a concurrent request with the same key is still in progress.
Example: dep_user42_1743152580
Response fields
dataKeystringExample: "pk_data_a1b2c3d4e5f6"
notestringOne-time display and client-embedding security guidance.
Response codes
201Data key issued.Short-lived tokens — OAuth client credentials
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:
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.
/oauth/token
Issue OAuth client-credentials access token
Full endpoint documentationcreateOAuthTokenIssues a short-lived Bearer token for partners that have OAuth client credentials enabled in their enterprise security policy. Provide the partner API key as the client secret via HTTP Basic auth, form body, or JSON body.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Request body
grant_typeclient_credentialsclient_idstringOptional partner client identifier. Defaults to the authenticated key document id.
client_secretstringRequiredPartner API key used as the client secret.
scopestringSpace-delimited scopes requested for the short-lived access token.
Example: "trading:write reports:read"
Response fields
access_tokenstringExample: "ms_oauth_..."
token_typestringExample: "Bearer"
expires_inintegerExample: 900
scopestringResponse codes
200Short-lived OAuth access token.403OAuth client credentials are not enabled for this partner.Firebase-token endpoints
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), GET /me?workspace=1 (verified-email access summary), POST /me (verified-email environment selection and personal deployment preference), 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.
Workspace actions are described in Partner workspace. They do not issue API keys or grant production authority. Installation license credentials are separate from API keys and Firebase user sessions; see Deployment options. Full keys, data keys and OAuth tokens remain subject to current Hosted authorization on every request. Installation evaluation cannot mint a Live console session.
Idempotency — safe retries for authenticated mutations
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 under the partner integration contract. The Firebase workspace POST /me actions are separate portal operations and do not use this mechanism. Other 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