New to OAuth2? Don’t worry about reading this whole page first — head to the Quick Start to get a working API call in a few minutes, then come back here when you need the details.
Endpoints
| Purpose | Endpoint |
|---|---|
| Authorization | https://app.aries.com/oauth2/authorize |
| Token exchange & refresh | POST https://api.aries.com/v1/oauth2/token |
Before you start
If OAuth2 is new to you, this is the easiest way to think about it:- Your app asks the user to sign in with Aries.
- Aries sends your app a short-lived authorization code.
- Your app sends that code to the token endpoint.
- Aries returns an access token and usually a refresh token.
- Your app uses the access token when calling Aries APIs.
POST /v1/oauth2/token.
That endpoint can be used in two different ways:
- Code exchange: trade an authorization code for tokens.
- Refresh: trade a refresh token for a new access token.
- Server-side / confidential client: send
client_secret - PKCE / public client: send
code_verifier
Key terms in plain English
| Term | What it means |
|---|---|
client_id | The public identifier for your app |
client_secret | A private password for your app. Only safe on a backend server |
authorization code | A short-lived one-time code Aries sends back after login |
access_token | The token you send with API requests |
refresh_token | A token you use later to get a new access token |
redirect_uri | The URL Aries sends the user back to after login |
scope | A list of permissions your app is asking for |
state | A random value used to protect the login flow from tampering |
code_verifier | A one-time secret used by PKCE instead of client_secret |
code_challenge | A hashed version of the code_verifier sent earlier in the flow |
If your app has a backend server that can safely store secrets, use the Authorization Code flow with
client_secret.
If your app runs in the browser or on a phone, use PKCE with code_verifier.Available Scopes
What’s a scope? A scope is a label that says “this app is allowed to do X.” When you redirect the user to log in, you pass a list of scopes you need. The consent screen shows the user exactly what you’re asking for, and the access token they approve will only work for those things. Rule of thumb: request the smallest set of scopes that lets your app do its job. Asking for more than you need scares users away on the consent screen and increases the blast radius if a token leaks.| Scope | Description | Example endpoints |
|---|---|---|
user:information | View user profile and personal details | PATCH /v1/users/meGET /v1/users/me/profile |
account:information | View account balances, positions, and transaction history | GET /v1/users/me/accountsGET /v1/accounts/{id}/balancesGET /v1/accounts/{id}/positions |
order:execution | Place, modify, and cancel orders | POST /v1/ordersPUT /v1/ordersDELETE /v1/orders |
order:information | View order history, status, and execution reports | GET /v2/accounts/{id}/orders |
position:information | View current positions and holdings | GET /v1/accounts/{id}/positions |
market:information | Access live and historical market data | GET /v1/marketdata/searchWSS /v1/market/ws |
calendar:information | Access earnings, economic, and market schedule data | GET /v1/calendars/economicsGET /v1/calendars/earnings |
options:information | Access options chains, Greeks, and expiration data | GET /v1/options/stocks/top-volumeGET /v1/options/etfs/top-volume |
analytics:information | View analytics, ratings, and market insights | GET /v1/analytics/ratingsGET /v1/analytics/market-breadth |
market:supplemental | Comprehensive market data: news, company profiles, financials, filings, ETF data, technical analysis | GET /v1/newsGET /v1/company/profileGET /v1/financials/statements |
Specify multiple scopes as a space-separated string:
account:information order:execution market:informationChoose your flow
There are two flows. Pick based on whether your app can keep a secret safe.Authorization Code Flow
Use if: your app has a backend server (Node, Python, Go, Ruby, PHP, etc.) that can hold a
client_secret that the user never sees. This is the standard, most-secure flow.PKCE Flow
Use if: your app runs entirely in the browser (single-page app) or on a mobile device, where any ‘secret’ you ship can be extracted. PKCE swaps the secret for a per-request proof your app generates on the fly.
How it works
Both flows follow this sequence. The only difference is in step 6 — how your app proves it’s really yours when trading the one-timecode for tokens:
- Authorization Code flow — your backend sends its
client_secretalong with thecode. - PKCE flow — your client sends a
code_verifier(a random value it generated before step 2 and has been holding onto) that mathematically matches thecode_challengeit sent at the start.
access_token (use this in API calls) and refresh_token (use this to get a new access token later without re-prompting the user).
What you send to the token endpoint
This is the part that usually confuses people, so here it is in a simple table.1. When you are exchanging a login code on a backend server
Send:grant_type: codeclient_idclient_secretcoderedirect_uri
client_secret private.
2. When you are exchanging a login code from a browser or mobile app
Send:grant_type: codeclient_idcoderedirect_uricode_verifier
client_secret here.
3. When your access token has expired and you want a new one
Send:grant_type: refresh_tokenclient_idclient_secretrefresh_token
The Aries backend uses a single request model for
/v1/oauth2/token. What changes is which fields are required for the situation you are in.Step-by-step walkthrough
Step 1: Register your app
Create an OAuth client in Client Center. You will get:- a
client_id - a
client_secretif your app is a confidential/server-side client
redirect_uri values your app will use.
Step 2: Send the user to Aries to sign in
Your app redirects the user to:https://app.aries.com/oauth2/authorize
At this stage, you tell Aries:
- which app is asking (
client_id) - where to send the user back (
redirect_uri) - which permissions you want (
scope) - which response you want (
response_type=code) - a random safety value (
state) - for PKCE only:
code_challengeandcode_challenge_method
Step 3: User signs in and approves
The user sees the Aries login and consent screen. If they approve, Aries sends them back to yourredirect_uri with a one-time code.
Step 4: Your app exchanges the code for tokens
Your app sends that code to:POST https://api.aries.com/v1/oauth2/token
This is where the flow splits:
- backend apps send
client_secret - browser/mobile apps send
code_verifier
access_tokenrefresh_tokenexpires_intoken_type- granted
scope
Step 5: Call Aries APIs
Now your app can call protected endpoints by sending:Step 6: Refresh when needed
When the access token expires, your app sends therefresh_token to the same token endpoint to get a new access token.
This means the user usually does not need to sign in again every time a token expires.
Security Best Practices
Store credentials securely
Never hardcode
client_secret or tokens in source code. Use environment variables or a secrets manager.Use HTTPS only
Always use HTTPS for redirect URIs and all API calls in production. Never transmit credentials over HTTP.
Validate the state parameter
Always generate and verify
state to prevent CSRF attacks. Generate a new random value per authorization request.Rotate tokens proactively
Refresh access tokens before they expire. Persist any newly issued
refresh_token returned in the response.Rate Limits
Rate limits vary by endpoint category:Authentication
10 requests/minute
User Management
100 requests/minute
Market Data
1,000 requests/minute
Trading
50 requests/minute
429 Too Many Requests), wait until X-RateLimit-Reset before retrying, or use exponential backoff.
Troubleshooting
invalid_grant — Authorization code expired or already used
invalid_grant — Authorization code expired or already used
invalid_client — Client authentication failed
invalid_client — Client authentication failed
Causes: Incorrect
Solution: Verify credentials in Client Center. Regenerate
client_id or client_secret, or the client was deleted or disabled.Solution: Verify credentials in Client Center. Regenerate
client_secret if lost (it is shown only once).invalid_scope — Requested scope is invalid
invalid_scope — Requested scope is invalid
Causes: Typo in scope name (case-sensitive) or scope not enabled for your client.
Solution: Check scope names against the Available Scopes table and client configuration.
Solution: Check scope names against the Available Scopes table and client configuration.
redirect_uri_mismatch
redirect_uri_mismatch
Causes: The
Solution: Register all redirect URIs in Client Center. Values must match character for character.
redirect_uri does not exactly match a registered URI (including protocol, path, and trailing slashes).Solution: Register all redirect URIs in Client Center. Values must match character for character.
access_denied — User denied authorization
access_denied — User denied authorization
Next steps
Authorization Code Flow
Implement server-side OAuth2 with
client_secret.PKCE Flow
Implement OAuth2 for SPAs and mobile apps without
client_secret.OAuth2 Token API
Token endpoint reference and interactive testing.
Quick Start
Get your first API call working in minutes.