> ## Documentation Index
> Fetch the complete documentation index at: https://finance.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth2 Token

> Exchanges authorization codes for access and refresh tokens, or uses refresh tokens to obtain new access tokens. This endpoint supports multiple OAuth2 grant types including authorization_code and refresh_token flows.

**Use Case:** Obtain API access tokens after user authorization or refresh expired tokens to maintain continuous API access for applications.




## OpenAPI

````yaml openapi.json POST /v1/oauth2/token
openapi: 3.0.3
info:
  contact:
    email: dev@aries.com
    name: Aries Financial
  description: >-
    OpenAPI Specification for the Aries trading platform API.


    # Authentication


    Learn how to authenticate with the Aries API using OAuth2 and manage access
    tokens in your SDK.


    ## Overview


    The Aries API uses **OAuth2 with Bearer tokens** (JWT format) for
    authentication. All API requests require a valid access token in the
    `Authorization` header:


    ```

    Authorization: Bearer <access_token>

    ```


    ## Providing Client ID and Client Secret (SDK)


    When using the generated SDK, provide your **Client ID** and **Client
    Secret** when you create the API client (e.g. in the constructor or security
    options). The SDK will use these to obtain and refresh the access token
    internally; you do not need to manage tokens yourself.


    Obtain your OAuth2 credentials from the Aries platform (e.g. Client Center /
    Manage Account at https://app.aries.com):


    - **Client ID** – Your application identifier (pass to SDK client)

    - **Client Secret** – Your application secret key (pass to SDK client; use
    PKCE for public clients where secret cannot be stored)


    ## Authentication Flow


    ### 1. Authorization Code Flow


    For server-side or confidential clients:


    1. **Redirect the user** to the authorization URL to sign in and consent:
     - **URL:** `https://app.aries.com/oauth2/authorize`
     - **Query params:** `response_type=code`, `client_id`, `redirect_uri`, `scope`, `state`

    2. **Exchange the code for tokens** (after user is redirected back with
    `?code=.`):
     - **POST** `https://api.aries.com/v1/oauth2/token`
     - **Body:** `grant_type=authorization_code`, `code`, `redirect_uri`, `client_id`, `client_secret`
     - Response includes `access_token` and `refresh_token`

    3. **Call the API** with the access token: `Authorization: Bearer
    <access_token>`


    ### 2. PKCE Flow


    For SPAs and mobile apps (public clients that cannot store `client_secret`):


    1. Generate a **code_verifier** (random string) and **code_challenge** =
    BASE64URL(SHA256(code_verifier)).

    2. **Redirect the user** to `https://app.aries.com/oauth2/authorize` with
    `code_challenge`, `code_challenge_method=S256`, plus `client_id`,
    `redirect_uri`, `scope`, `state`.

    3. **Exchange the code** at POST `https://api.aries.com/v1/oauth2/token`
    with `grant_type=authorization_code`, `code`, `redirect_uri`, `client_id`,
    `code_verifier` (no client_secret).

    4. Use the returned `access_token` as Bearer.


    ### 3. MFA Verification


    If the user has MFA enabled, the authorize step may return `is_mfa: true`
    and a `next_step_auth_id`. Call **POST**
    `https://api.aries.com/v1/oauth2/authorize/mfa` with `next_step_auth_id` and
    `verification_code` (6-digit code). Then continue with **POST**
    `/v1/oauth2/authorize/confirm` to get the authorization code, and exchange
    it at `/v1/oauth2/token`.


    ## Token Management


    - **Refresh when expired:** POST `https://api.aries.com/v1/oauth2/token`
    with `grant_type=refresh_token`, `client_id`, `client_secret`,
    `refresh_token`.

    - **Using a Bearer token directly:** If you already have an access token,
    set the header `Authorization: Bearer <access_token>` on every request. The
    SDK can accept a pre-obtained token and use it until it expires.


    ## OAuth2 Scopes


    Request only the scopes your application needs. Available scopes:


    | Scope | Description |

    |-------|-------------|

    | `user:information` | View user profile and personal details |

    | `account:information` | View account balances, positions, and transaction
    history |

    | `order:execution` | Place, modify, and cancel orders |

    | `order:information` | View order history and status |

    | `position:information` | View current positions and holdings |

    | `market:information` | Access live and historical market data |

    | `calendar:information` | Access earnings, economic, and market schedule
    data |

    | `options:information` | Access options chains and expiration data |

    | `analytics:information` | View analytics, ratings, and market insights |

    | `market:supplemental` | News, company profiles, financials, filings, ETF
    data, technical analysis |


    Specify multiple scopes as a space-separated string, e.g.
    `account:information order:execution market:information`.


    ## Security Best Practices


    - **Store credentials securely** – Use environment variables or a secrets
    manager for `client_id` and `client_secret`. Never hardcode them.

    - **Handle token expiration** – Check for 401 responses and refresh the
    token using the refresh_token, then retry the request.

    - **Use HTTPS** – All authorization and token endpoints must be called over
    HTTPS.

    - **Validate state** – When using the authorization code flow, validate the
    `state` parameter on the callback to prevent CSRF.


    ## Error Handling


    - **400 Bad Request** – Invalid or missing parameters, validation failures,
    or malformed JSON. Response bodies follow the same patterns as other errors
    (flat `error` string, optional `codes`, nested `error` object, or rarely no
    body).


    - **401 Unauthorized** – Invalid or expired access token; refresh the token
    or re-authenticate. JSON bodies are not identical on every route: you may
    see a flat `error` string (sometimes with `codes`), a nested `error` object
    (`type`, `code`, `message`), or rarely an empty body


    - **403 Forbidden** – Insufficient scope or permissions for the requested
    resource. Error JSON may be flat or nested, like 400/401.


    - **404 Not Found** – Resource does not exist or is not visible. Error JSON
    may be flat or nested.


    - **429 Too Many Requests** – Rate limit exceeded; slow down and respect
    `Retry-After` when the header is present. Error JSON may be flat or nested.


    - **500 / 5xx** – Server or upstream failure; retry with backoff. Do not
    depend on a single error JSON shape; some responses may have no body.



    ---


    Endpoints in this spec: health, OAuth2 (authorize, confirm, mfa, token),
    users, accounts, orders, market data, watchlist, chart, analytics,
    calendars, company, economy, financials, indices, options, news, and
    supplemental data.
  title: Aries API — OpenAPI Specification
  version: 1.0.0
servers:
  - description: Production server
    url: https://api.aries.com
security: []
tags:
  - description: >-
      Analytics endpoints for market data analysis including top gainers,
      losers, volume leaders, sector analysis, analyst ratings, market breadth,
      and net inflow
    name: Analytics
  - description: User management and profile endpoints
    name: Users
  - description: >-
      Order management endpoints for placing, updating, canceling, and
      previewing orders
    name: Orders
  - description: Account management endpoints for positions, orders, and balances
    name: Accounts
  - description: Calendar and mergers/acquisitions endpoints
    name: Calendar
  - description: >-
      Market data endpoints for symbol search, real-time data access, and equity
      details
    name: Market Data
  - description: >-
      Watchlist endpoints for listing, creating, updating, and deleting
      watchlists
    name: Watchlist
  - description: Chart endpoints for config, symbols, history, quotes, and server time
    name: Chart
  - description: News and news sentiment endpoints
    name: News
  - description: >-
      Indices endpoints for groups, list, search, bar, bars, chart-bars,
      realtime values
    name: Indices
  - description: Logos search and sync endpoints
    name: Logos
  - description: 'Corporate actions: spinoffs, tender offers, IPO calendar, dividends'
    name: Corporate Actions
  - description: 'Economy endpoints: inflation, inflation expectations, treasury yields'
    name: Economy
  - description: >-
      Options endpoints: expiry dates, contracts, activity, trades, quotes,
      unusual activity
    name: Options
  - description: >-
      Financials: reported, statements, revenue breakdown, short volume, ratios,
      short interest
    name: Financials
  - description: Signals and bull-bear cases
    name: Signals
  - name: Company
  - name: ETF
  - name: Filings
  - name: Market
  - name: Ownership
  - name: Stocks
  - name: Stock Estimates
  - name: Stock Alternative
    description: >-
      Transcripts, company presentation, social sentiment, investment themes,
      supply chain, and ESG data
  - name: Technical Analysis
paths:
  /v1/oauth2/token:
    post:
      tags:
        - OAuth2
      summary: Exchange OAuth2 code or refresh token
      description: >-
        Exchanges an authorization code for access and refresh tokens, exchanges
        a PKCE authorization code using a `code_verifier`, or refreshes an
        existing access token using a refresh token. This endpoint issues tokens
        and does not require an existing Bearer token.
      operationId: oauth2Token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/OAuth2TokenAuthorizationCodeRequest'
                - $ref: '#/components/schemas/OAuth2TokenPkceRequest'
                - $ref: '#/components/schemas/OAuth2TokenRefreshRequest'
            examples:
              authorizationCode:
                summary: Authorization Code
                value:
                  grant_type: authorization_code
                  code: auth_code_abc123xyz789def456
                  client_id: client_abc123xyz
                  client_secret: secret_xyz789abc
                  redirect_uri: https://yourapp.com/callback
              pkce:
                summary: PKCE
                value:
                  grant_type: authorization_code
                  code: auth_code_abc123xyz789def456
                  client_id: client_abc123xyz
                  redirect_uri: https://yourapp.com/callback
                  code_verifier: verifier_abc123xyz789def456
              refreshToken:
                summary: Refresh Token
                value:
                  grant_type: refresh_token
                  refresh_token: refresh_token_abc123xyz789def456
                  client_id: client_abc123xyz
                  client_secret: secret_xyz789abc
      responses:
        '200':
          description: Tokens issued successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuth2TokenResponse'
              example:
                access_token: >-
                  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature
                refresh_token: >-
                  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWYiOiIxMjM0NTY3ODkwIn0.signature
                token_type: Bearer
                expires_in: 3600
                refresh_token_expires_in: 2592000
                scope: read write
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security: []
components:
  schemas:
    OAuth2TokenAuthorizationCodeRequest:
      title: Authorization Code
      type: object
      description: >-
        Use this when your app has a backend server and can safely store a
        client secret. Exchange a one-time authorization code for tokens by
        sending `client_secret`.
      properties:
        client_id:
          type: string
          description: OAuth2 client identifier.
        client_secret:
          type: string
          description: OAuth2 client secret for confidential server-side apps.
        code:
          type: string
          description: Authorization code returned from the authorize or confirm flow.
        grant_type:
          type: string
          description: >-
            Grant type for code exchange. The backend accepts
            `authorization_code` and normalizes it internally.
          enum:
            - code
            - authorization_code
          example: authorization_code
        redirect_uri:
          type: string
          description: Redirect URI used earlier in the login flow. Must match exactly.
          example: https://yourapp.com/callback
      required:
        - client_id
        - client_secret
        - code
        - grant_type
        - redirect_uri
    OAuth2TokenPkceRequest:
      title: PKCE
      type: object
      description: >-
        Use this when your app runs in the browser or on a mobile device and
        cannot safely store a client secret. Exchange a one-time authorization
        code by sending `code_verifier` instead of `client_secret`.
      properties:
        client_id:
          type: string
          description: OAuth2 client identifier.
        code:
          type: string
          description: Authorization code returned from the authorize or confirm flow.
        grant_type:
          type: string
          description: >-
            Grant type for PKCE code exchange. The backend accepts
            `authorization_code` and normalizes it internally.
          enum:
            - code
            - authorization_code
          example: authorization_code
        redirect_uri:
          type: string
          description: Redirect URI used earlier in the login flow. Must match exactly.
          example: https://yourapp.com/callback
        code_verifier:
          type: string
          description: >-
            Original PKCE verifier generated by your app before redirecting the
            user.
      required:
        - client_id
        - code
        - grant_type
        - redirect_uri
        - code_verifier
    OAuth2TokenRefreshRequest:
      title: Refresh Token
      type: object
      description: >-
        Use this after you already have tokens and only need a fresh access
        token. Send the refresh token previously issued by Aries.
      properties:
        client_id:
          type: string
          description: OAuth2 client identifier.
        client_secret:
          type: string
          description: OAuth2 client secret used for refresh requests.
        grant_type:
          type: string
          description: Grant type for refreshing an expired access token.
          enum:
            - refresh_token
          example: refresh_token
        refresh_token:
          type: string
          description: Refresh token previously issued by Aries.
      required:
        - client_id
        - client_secret
        - grant_type
        - refresh_token
    OAuth2TokenResponse:
      type: object
      description: >-
        OAuth2 token response. Fields may vary slightly by flow and server
        behavior, so response properties are documented without a required list.
      properties:
        access_token:
          type: string
          description: OAuth2 access token used in the Authorization header.
        refresh_token:
          type: string
          description: Refresh token used to obtain a new access token later.
        token_type:
          type: string
          description: Token type returned by the server, typically Bearer.
          example: Bearer
        expires_in:
          type: integer
          description: Access token lifetime in seconds.
          example: 3600
        refresh_token_expires_in:
          type: integer
          description: Refresh token lifetime in seconds.
          example: 2592000
        scope:
          type: string
          description: Space-separated scopes granted for this token.
          example: read write
    AuthenticationErrorEnvelope:
      type: object
      description: >-
        JSON envelope where `error` is a nested object (`type`, `code`,
        `message`, …). Many services use this shape for 400, 401, 403, 404, 429,
        and 5xx when using the shared HTTP error format.
      properties:
        error:
          $ref: '#/components/schemas/AuthenticationErrorDetail'
        meta:
          type: object
          additionalProperties: true
          description: Optional metadata
    ErrorResponse:
      properties:
        codes:
          description: Structured error codes for programmatic handling
          items:
            $ref: '#/components/schemas/ErrorCode'
          type: array
        error:
          type: string
          description: >-
            Error detail as a string. Exact message content is not fixed and
            should not be hard-coded.
          example: string
        metadata:
          additionalProperties: true
          description: Additional error context
          type: object
      type: object
    AuthenticationErrorDetail:
      type: object
      description: >-
        Structured payload for the nested `error` object. Services using the
        shared Go error writer emit uppercase `type` values aligned with error
        categories (for example `VALIDATION`, `BAD_REQUEST`, `AUTHENTICATION`,
        `AUTHORIZATION`, `NOT_FOUND`, `RATE_LIMIT`, `INTERNAL`).
      properties:
        type:
          type: string
          description: >-
            Error category emitted by the shared error writer, such as
            VALIDATION, BAD_REQUEST, AUTHENTICATION, AUTHORIZATION, NOT_FOUND,
            RATE_LIMIT, or INTERNAL.
          example: AUTHENTICATION
        code:
          type: string
          description: Machine-readable code
          example: INVALID_TOKEN
        message:
          type: string
          description: >-
            Error detail as a string. Exact message content is not fixed and
            should not be hard-coded.
          example: string
        details:
          type: object
          additionalProperties: true
          description: Optional extra context
        request_id:
          type: string
          description: Request correlation id when provided
    ErrorCode:
      properties:
        code:
          description: Machine-readable error code
          example: INVALID_PASSWORD
          type: string
        description:
          description: Human-readable description of the error
          example: Password must be between 8 and 64 characters
          type: string
        field:
          description: Field name that caused the error
          example: password
          type: string
      type: object
  responses:
    BadRequest:
      description: >-
        Invalid query/path/body, malformed JSON, or failed validation.


        **Backend (shared HTTP errors):** Routes that use the shared error
        writer typically return a **nested** JSON object: `error.type` is an
        uppercase category such as `VALIDATION` or `BAD_REQUEST` (see the API
        implementation). Other routes may return the **flat** `ErrorResponse`
        shape (`error` as a string, optional `codes`). The body may rarely be
        empty.


        **OpenAPI:** Every operation’s **400** response references this
        component so the documented schema and examples stay aligned.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/AuthenticationErrorEnvelope'
              - $ref: '#/components/schemas/ErrorResponse'
            description: >-
              400 responses commonly use a nested `error` object (`type`,
              `code`, `message`, optional `details`). Some services still return
              flat `ErrorResponse` (`error` string, optional `codes`).
          examples:
            nested_shared_http_error:
              summary: Nested error (typical for shared WriteHTTPError-style responses)
              value:
                error:
                  type: VALIDATION
                  code: VALIDATION_ERROR
                  message: Query parameter validation failed
                  details:
                    fieldName: field is required
            nested_bad_request:
              summary: Nested error (BAD_REQUEST / invalid JSON)
              value:
                error:
                  type: BAD_REQUEST
                  code: INVALID_JSON
                  message: string
            flat_string:
              summary: Flat error string
              value:
                error: string
            flat_with_codes:
              summary: Flat error with field codes (some services)
              value:
                error: string
                codes:
                  - field: string
                    code: string
                    description: string
    Unauthorized:
      description: >-
        Authentication failed: missing credentials, invalid JWT, or expired
        access token.


        **Response body variants:** Some routes return JSON with a string
        `error` field (and optionally `codes` / `metadata`). Others return JSON
        where `error` is a structured object (`type`, `code`, `message`, and
        optionally `details`, `request_id`). In edge cases (for example certain
        gateway or middleware paths) the response may have **no body** even
        though the status is 401—clients should treat 401 as unauthenticated and
        refresh or re-authenticate regardless of body shape.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorResponse'
              - $ref: '#/components/schemas/AuthenticationErrorEnvelope'
            description: >-
              401 responses may use a flat `ErrorResponse` shape or a nested
              `error` object. Inspect `error`: if it is a string, use the flat
              shape; if it is an object, use the structured shape.
          examples:
            flat_message:
              summary: Flat error string (typical)
              value:
                error: string
            flat_with_codes:
              summary: Flat error with structured codes
              value:
                error: string
                codes:
                  - code: string
                    description: string
            nested_error_object:
              summary: Nested error (shared HTTP error format)
              value:
                error:
                  type: AUTHENTICATION
                  code: INVALID_TOKEN
                  message: string
    Forbidden:
      description: >-
        Authenticated but not allowed to perform this action or access this
        resource (insufficient scope or role).


        **Response body variants:** Flat `ErrorResponse` or nested `error`
        object, same pattern as 400/401.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorResponse'
              - $ref: '#/components/schemas/AuthenticationErrorEnvelope'
            description: 403 responses may use a flat or nested error shape.
          examples:
            flat:
              summary: Flat message
              value:
                error: string
            nested:
              summary: Nested error (shared HTTP error format)
              value:
                error:
                  type: AUTHORIZATION
                  code: INSUFFICIENT_SCOPE
                  message: string
    RateLimitExceeded:
      description: >-
        Too many requests for this client or IP. **Slow down** and retry after a
        delay.


        **Headers:** When present, `Retry-After` indicates how long to wait
        (seconds or an HTTP-date).


        **Body:** Flat `ErrorResponse` or nested `error` object, same as other
        errors.
      headers:
        Retry-After:
          description: >-
            Seconds to wait before retrying, or an HTTP-date (RFC 7231). Omitted
            if not applicable.
          schema:
            type: string
            example: '60'
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorResponse'
              - $ref: '#/components/schemas/AuthenticationErrorEnvelope'
            description: 429 responses may use a flat or nested error shape.
          examples:
            flat:
              summary: Flat rate-limit message
              value:
                error: string
            nested:
              summary: Nested error (shared HTTP error format)
              value:
                error:
                  type: RATE_LIMIT
                  code: TOO_MANY_REQUESTS
                  message: string
    InternalServerError:
      description: >-
        Unexpected server error or upstream failure. **Retry with exponential
        backoff**; do not assume a specific JSON body shape.


        **Response body variants:** Flat `ErrorResponse`, nested `error` object,
        or occasionally a minimal message. Some paths may return **no body**.
      content:
        application/json:
          examples:
            flat_string:
              summary: Flat error string
              value:
                error: string
            nested_error_object:
              summary: Nested error (shared HTTP error format)
              value:
                error:
                  type: INTERNAL
                  code: INTERNAL_ERROR
                  message: string
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorResponse'
              - $ref: '#/components/schemas/AuthenticationErrorEnvelope'
            description: 5xx responses may use a flat or nested error shape.

````