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

# Post apiv1oauthtoken

> RFC 6749 client-credentials grant for active service accounts. Supply grant_type=client_credentials, client_id=<service-account UUID>, and client_secret=<full tfk_live_... or tfk_test_... service-account API key>. Client credentials may instead be sent with HTTP Basic authentication. Tokens use the configured auth.jwtExpirySeconds capped at 900 seconds and carry the service account's current workspace role, effective permissions, and effective API scopes.



## OpenAPI

````yaml /api-reference/openapi.json post /api/v1/oauth/token
openapi: 3.1.0
info:
  description: >-
    TetraFi is an API for institutional trading across on-chain and off-chain
    venues: discover assets, request quotes, place an order by quote id and read
    its status. API keys sign every request.


    Asset-pair quotes: every tagged union is tagged by `kind`; only the outcome
    of `/prices` rows and `sources[]` entries is tagged by `status`.
  title: TetraFi API
  version: 1.0.0-beta.1
servers:
  - url: https://api.tetrafi.io
security:
  - api_key: []
tags:
  - description: Request price quotes from multiple solvers for cross-chain transactions
    name: quotes
  - description: Submit, track, and manage cross-chain orders
    name: orders
  - description: Canonical trading pairs and aggregator metadata
    name: trading
  - description: >-
      Authentication — registration, login, SIWE, OAuth, sessions, login
      activity
    name: auth
  - description: Workspace CRUD, settings, members, and team management
    name: workspaces
  - description: >-
      Webhook management — CRUD, secret rotation, test delivery, delivery
      history
    name: webhooks
paths:
  /api/v1/oauth/token:
    post:
      tags:
        - auth
      description: >-
        RFC 6749 client-credentials grant for active service accounts. Supply
        grant_type=client_credentials, client_id=<service-account UUID>, and
        client_secret=<full tfk_live_... or tfk_test_... service-account API
        key>. Client credentials may instead be sent with HTTP Basic
        authentication. Tokens use the configured auth.jwtExpirySeconds capped
        at 900 seconds and carry the service account's current workspace role,
        effective permissions, and effective API scopes.
      operationId: oauth_token
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/OAuthTokenRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthTokenResponse'
          description: Short-lived service-account bearer token
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthErrorResponse'
          description: >-
            invalid_grant (no grant_type, or an unreadable form),
            unsupported_grant_type (a grant other than client_credentials), or
            unauthorized_client with error_uri naming
            SIGNED_KEY_NOT_EXCHANGEABLE (a key that requires request signing or
            holds venue trading signs each request instead)
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthErrorResponse'
          description: >-
            invalid_client: the client id or secret is wrong, or the key is not
            an active service account's
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthErrorResponse'
          description: >-
            temporarily_unavailable: the client's current authority could not be
            read; retry
      security:
        - {}
components:
  schemas:
    OAuthTokenRequest:
      description: >-
        An RFC 6749 client-credentials token request, form-encoded. Its field
        names are the

        standard's, so OAuth client libraries send it unchanged.
      properties:
        client_id:
          description: >-
            The service account's id. Omit it when the credentials are sent with
            HTTP Basic.
          type:
            - string
            - 'null'
        client_secret:
          description: >-
            The service account's full API key (`tfk_live_…` or `tfk_test_…`).
            Omit it when the

            credentials are sent with HTTP Basic.
          type:
            - string
            - 'null'
        grant_type:
          description: Always `client_credentials`.
          type:
            - string
            - 'null'
      type: object
    OAuthTokenResponse:
      description: An RFC 6749 access token response.
      properties:
        access_token:
          description: 'The bearer token: send it as `Authorization: Bearer <access_token>`.'
          type: string
        expires_in:
          description: >-
            Seconds until the token expires (at most 900). Request a new one
            before then.
          format: int64
          minimum: 0
          type: integer
        scope:
          description: The token's API scopes, space-separated.
          type: string
        token_type:
          description: Always `Bearer`.
          type: string
      required:
        - access_token
        - token_type
        - expires_in
        - scope
      type: object
    OAuthErrorResponse:
      description: >-
        An RFC 6749 error response: the token endpoint answers the standard's
        body, not `ApiError`.
      properties:
        error:
          description: >-
            The RFC 6749 error code: `invalid_client` (401), `invalid_grant`,
            `unsupported_grant_type`

            or `unauthorized_client` (400), or `temporarily_unavailable` (503).
          type: string
        error_description:
          description: >-
            Why the client was refused, when the RFC 6749 code alone does not
            say.
          type:
            - string
            - 'null'
        error_uri:
          description: >-
            The error-code reference for a TetraFi cause the RFC 6749 code does
            not name

            (`SIGNED_KEY_NOT_EXCHANGEABLE`).
          type:
            - string
            - 'null'
      required:
        - error
      type: object
  securitySchemes:
    api_key:
      description: >-
        Send the API key in `X-API-Key`.


        **Request signing.** A key with signing enabled (`POST
        /api/v1/workspaces/{workspaceId}/users/me/api-keys/{keyId}/signing`,
        which returns the signing secret once) must also sign every request:


        - `X-Timestamp`: the current Unix time in seconds, within 300 seconds of
        the server clock.

        - `X-Signature`: lower-case hex HMAC-SHA256 of the canonical string,
        keyed with the signing secret's 32 bytes (the secret is 64 hex
        characters; decode it first).


        The canonical string is four lines joined by `\n`, with no trailing
        newline: the `X-Timestamp` value, the upper-case method, the path with
        its query exactly as sent (`/api/v1/orders?limit=1`), and the lower-case
        hex SHA-256 of the exact body bytes (the SHA-256 of an empty body when
        there is none).


        A write's signature (POST, PUT, PATCH, DELETE) is accepted once: sending
        the same signed write again is refused, so a retry signs again. A read
        (GET, HEAD) changes nothing, so an identical signed read inside the
        window is admitted again and polling needs no nonce.


        A signing refusal is a 401 `AUTH_REQUIRED` whose `details.reason` names
        the cause: `SIGNATURE_REQUIRED` (a header is missing),
        `SIGNATURE_INVALID` (a malformed header or a wrong signature),
        `TIMESTAMP_OUT_OF_RANGE` or `SIGNATURE_REPLAYED`.
      in: header
      name: X-API-Key
      type: apiKey
      x-request-signing:
        algorithm: HMAC-SHA256
        canonicalRequest:
          - timestamp
          - method
          - pathWithQuery
          - bodySha256Hex
        canonicalSeparator: |+

        oneTimeMethods:
          - POST
          - PUT
          - PATCH
          - DELETE
        refusal:
          error: AUTH_REQUIRED
          reasons:
            - SIGNATURE_REQUIRED
            - SIGNATURE_INVALID
            - TIMESTAMP_OUT_OF_RANGE
            - SIGNATURE_REPLAYED
          status: 401
        secretEncoding: hex
        signatureEncoding: hex-lower
        signatureHeader: X-Signature
        timestampHeader: X-Timestamp
        timestampWindowSeconds: 300

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.