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

# Retrieve a trade

> Returns a single trade by ID.



## OpenAPI

````yaml api-reference/openapi-v3.json GET /v3/fx/trades/{id}
openapi: 3.1.0
info:
  title: OpenFX API v3
  version: v3.0.0
  summary: >-
    OpenFX v3: FX trading and balance movements, including deposits,
    withdrawals, and settlement.
  description: >-
    FX trading and balance movements, including deposits, withdrawals, and
    settlement. Every operation uses the `/v3/fx/...` wire prefix. Start with
    the [overview](/v3/introduction).
  termsOfService: https://www.openfx.com/terms
  contact:
    name: OpenFX Support
    email: support@openfx.com
    url: https://www.openfx.com
  license:
    name: Proprietary — © OpenFX. All rights reserved.
    url: https://www.openfx.com/terms
servers:
  - url: https://api.openfx.com
    description: >-
      OpenFX API. Same base URL serves sandbox and production; see
      [Environments](/v3/environments).
security:
  - bearerAuth: []
    requestSignatureAuth: []
tags:
  - name: Trade
    description: >-
      Discover tradable currency pairs, quote FX rates, and execute trades
      against OpenFX liquidity. Quote-then-trade workflow.
  - name: Trade Settlement
    description: >-
      Account-side flows in the Trade product: balances, deposits, withdrawals,
      and verified withdrawal accounts.
  - name: Exposure
    description: >-
      The organization's credit exposure: total credit line, amount currently
      committed to unsettled FX trades, and the breakdown by currency and
      settlement stage.
  - name: Webhooks
    description: >-
      Signed event deliveries for deposit and withdrawal lifecycle changes. The
      delivery envelope, signature scheme, and per-rail payloads are documented
      in the Webhooks guides.
paths:
  /v3/fx/trades/{id}:
    get:
      tags:
        - Trade
      summary: Retrieve a trade
      description: Returns a single trade by ID.
      operationId: getTrade
      parameters:
        - name: id
          in: path
          required: true
          description: Trade ID.
          schema:
            $ref: '#/components/schemas/ResourceIdInput'
        - $ref: '#/components/parameters/XRequestId'
      responses:
        '200':
          description: The trade.
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Trade'
              example:
                data:
                  object: trade
                  id: tde_5W7guYdHT24JFnRQrZN9y8
                  quoteId: qte_3FfGK34vwMvVFDedyb2nkf
                  buyCurrency: USDC
                  sellCurrency: USD
                  executedAmount: '999.8'
                  status: EXECUTED
                  clientReferenceId: order-123
                  createdAt: '2026-04-28T10:00:00.000Z'
                  settlementWindow: T0
                  settlementStartTime: '2026-04-28T10:00:30.000Z'
        '400':
          description: >-
            Schema-level validation failed. The JSON is malformed, has wrong
            types, or is missing required fields. See `error.details.issues` for
            the per-field errors. Semantic violations (well-formed but
            business-rule-invalid) return **422** instead.
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                validation_path_failed:
                  summary: VALIDATION_PATH_FAILED
                  value:
                    error:
                      code: VALIDATION_PATH_FAILED
                      type: VALIDATION_ERROR
                      message: >-
                        A URL path parameter failed validation. Check the path
                        against the API reference.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        issues:
                          - path: /v3/fx/example
                            code: invalid_type
                            message: Expected string, received number
        '401':
          description: >-
            Authentication failed. The bearer JWT, API key, or
            `X-Request-Signature` header is missing, invalid, malformed,
            replayed, or expired. Environment-mismatch errors (sandbox key vs
            live mode, etc.) return **403** instead, since the request was
            authenticated but rejected by environment policy.
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                auth_token_missing:
                  summary: AUTH_TOKEN_MISSING
                  value:
                    error:
                      code: AUTH_TOKEN_MISSING
                      type: AUTHENTICATION_ERROR
                      message: The Authorization header is required.
                      retryStrategy: TERMINAL
                      details: {}
                auth_token_invalid:
                  summary: AUTH_TOKEN_INVALID
                  value:
                    error:
                      code: AUTH_TOKEN_INVALID
                      type: AUTHENTICATION_ERROR
                      message: >-
                        Authorization token is invalid. Issue a fresh JWT. If
                        you sign requests, confirm the X-Request-Signature uses
                        IEEE P-1363 fixed 64-byte r‖s (not DER) over the
                        canonical string, and that the body was not
                        re-serialized between hashing and sending.
                      retryStrategy: TERMINAL
                      details: {}
                auth_token_expired:
                  summary: AUTH_TOKEN_EXPIRED
                  value:
                    error:
                      code: AUTH_TOKEN_EXPIRED
                      type: AUTHENTICATION_ERROR
                      message: >-
                        The authorization token is expired. Provide an active
                        authorization token in the request header.
                      retryStrategy: TERMINAL
                      details: {}
                auth_token_invalid_config:
                  summary: AUTH_TOKEN_INVALID_CONFIG
                  value:
                    error:
                      code: AUTH_TOKEN_INVALID_CONFIG
                      type: AUTHENTICATION_ERROR
                      message: >-
                        Authorization token configuration is invalid. Check the
                        token's validity window (max 60 seconds) and clock skew.
                      retryStrategy: TERMINAL
                      details:
                        reason: SIGNATURE_INVALID
                auth_api_key_missing:
                  summary: AUTH_API_KEY_MISSING
                  value:
                    error:
                      code: AUTH_API_KEY_MISSING
                      type: AUTHENTICATION_ERROR
                      message: The authorization token does not reference an API key.
                      retryStrategy: TERMINAL
                      details: {}
                auth_api_key_invalid:
                  summary: AUTH_API_KEY_INVALID
                  value:
                    error:
                      code: AUTH_API_KEY_INVALID
                      type: AUTHENTICATION_ERROR
                      message: The API key is inactive or does not exist.
                      retryStrategy: TERMINAL
                      details: {}
        '403':
          description: >-
            Authenticated, but not authorized. Common causes: wrong scope, wrong
            environment, IP blocked, account disabled, or pair/currency not
            enabled for your org.
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                auth_api_key_sandbox_required:
                  summary: AUTH_API_KEY_SANDBOX_REQUIRED
                  value:
                    error:
                      code: AUTH_API_KEY_SANDBOX_REQUIRED
                      type: AUTHORIZATION_ERROR
                      message: >-
                        Sandbox traffic requires a Sandbox API key. Switch to a
                        Sandbox key in the dashboard.
                      retryStrategy: TERMINAL
                      details: {}
                auth_api_key_live_required:
                  summary: AUTH_API_KEY_LIVE_REQUIRED
                  value:
                    error:
                      code: AUTH_API_KEY_LIVE_REQUIRED
                      type: AUTHORIZATION_ERROR
                      message: Live traffic requires a Live API key.
                      retryStrategy: TERMINAL
                      details: {}
                sandbox_mode_required:
                  summary: SANDBOX_MODE_REQUIRED
                  value:
                    error:
                      code: SANDBOX_MODE_REQUIRED
                      type: AUTHORIZATION_ERROR
                      message: Sandbox requests must declare Sandbox mode.
                      retryStrategy: TERMINAL
                      details: {}
                auth_forbidden_ip:
                  summary: AUTH_FORBIDDEN_IP
                  value:
                    error:
                      code: AUTH_FORBIDDEN_IP
                      type: AUTHORIZATION_ERROR
                      message: >-
                        Source IP is not on the API key's allowlist. Update the
                        IP allowlist in the dashboard.
                      retryStrategy: TERMINAL
                      details: {}
                auth_insufficient_scope:
                  summary: AUTH_INSUFFICIENT_SCOPE
                  value:
                    error:
                      code: AUTH_INSUFFICIENT_SCOPE
                      type: AUTHORIZATION_ERROR
                      message: >-
                        API key is missing the scope required for this
                        operation. Grant the required scope to the key in the
                        dashboard.
                      retryStrategy: TERMINAL
                      details:
                        requiredScope: trade
                feature_not_enabled:
                  summary: FEATURE_NOT_ENABLED
                  value:
                    error:
                      code: FEATURE_NOT_ENABLED
                      type: AUTHORIZATION_ERROR
                      message: >-
                        You aren't allowed to perform this action. Contact the
                        support desk with the trace ID for assistance.
                      retryStrategy: TERMINAL
                      details: {}
        '404':
          description: >-
            The requested resource does not exist or is not visible to your
            account.
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                trade_not_found:
                  summary: TRADE_NOT_FOUND
                  value:
                    error:
                      code: TRADE_NOT_FOUND
                      type: NOT_FOUND
                      message: The requested trade was not found.
                      retryStrategy: TERMINAL
                      details:
                        tradeId: tde_5W7guYdHT24JFnRQrZN9y8
        '405':
          description: >-
            The HTTP method is not supported on the requested path. The `Allow`
            header lists the methods that are. Treat this as a client routing
            bug: fix the verb and resubmit.
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            Allow:
              $ref: '#/components/headers/Allow'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                method_not_allowed:
                  summary: METHOD_NOT_ALLOWED
                  value:
                    error:
                      code: METHOD_NOT_ALLOWED
                      type: VALIDATION_ERROR
                      message: This HTTP method is not supported on the requested path.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        method: POST
                        allowed:
                          - GET
        '429':
          description: >-
            Rate limit exceeded. Wait `Retry-After` seconds before retrying, or
            compute the wait from `RateLimit-Reset` (also a duration in
            seconds).
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                rate_limit_exceeded:
                  summary: RATE_LIMIT_EXCEEDED
                  value:
                    error:
                      code: RATE_LIMIT_EXCEEDED
                      type: RATE_LIMITED
                      message: Too many requests. Try again after the window resets.
                      retryStrategy: WAIT_THEN_RETRY_SAME_KEY
                      details: {}
        '500':
          description: >-
            Unexpected server error. The catch-all for failures that don't
            surface as a domain code — both unhandled exceptions and unmapped
            upstream rejections fold into this bucket. For money-movement
            writes, GET the resource by ID (using `resourceId` from `details`
            when present) before retrying; for reads, retry with exponential
            backoff. Include the `X-Trace-Id` when contacting support.
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                internal_error:
                  summary: INTERNAL_ERROR
                  value:
                    error:
                      code: INTERNAL_ERROR
                      type: INTERNAL_ERROR
                      message: >-
                        An unexpected error occurred. Check the state of the
                        resource before retrying writes; for reads, retry with
                        backoff. Contact the support desk if the failure
                        persists.
                      retryStrategy: CHECK_STATE_THEN_RETRY
                      details: {}
      externalDocs:
        url: https://docs.openfx.com/v3/trading
        description: >-
          Trading guide: trade record fields, statuses, and post-timeout
          reconciliation.
      x-codeSamples:
        - lang: curl
          source: >-
            # X-Request-Signature is an ES256 signature; compute it with one of
            the

            # language helpers in /v3/authentication (shell signing is
            impractical).

            curl https://api.openfx.com/v3/fx/trades/tde_5W7guYdHT24JFnRQrZN9y8
            \
              -H "Authorization: Bearer $OPENFX_JWT" \
              -H "X-Request-Signature: $OPENFX_SIGNATURE"
        - lang: JavaScript
          source: >-
            // signRequest mints a fresh 60s JWT AND the matching
            X-Request-Signature. See Authentication

            const tradeId = 'tde_5W7guYdHT24JFnRQrZN9y8';

            const url = `https://api.openfx.com/v3/fx/trades/${tradeId}`;

            const signed = signRequest({ method: 'GET', url, body: '' });

            const trade = await fetch(url, { headers: signed.headers }).then(r
            => r.json());
        - lang: Python
          source: >-
            import requests

            # sign_request mints a fresh 60s JWT AND the matching
            X-Request-Signature. See Authentication

            trade_id = 'tde_5W7guYdHT24JFnRQrZN9y8'

            url = f'https://api.openfx.com/v3/fx/trades/{trade_id}'

            headers, _ = sign_request('GET', url)

            trade = requests.get(url, headers={**headers}).json()
components:
  schemas:
    ResourceIdInput:
      type: string
      pattern: >-
        ^([a-z]{3,5}_[1-9A-HJ-NP-Za-km-z]{1,22}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$
      description: >-
        Accepts either the current readable, typed-prefix ID (see ResourceId) or
        a legacy bare UUID v4, for backward compatibility with IDs persisted
        before v3 introduced readable IDs. Both forms resolve to the same
        underlying record. Responses always return the readable form — see
        [Resource IDs](/v3/resource-ids).
      example: tde_5W7guYdHT24JFnRQrZN9y8
    Trade:
      type: object
      description: A trade executes against a quote at the quoted rate.
      required:
        - object
        - id
        - quoteId
        - buyCurrency
        - sellCurrency
        - executedAmount
        - status
        - clientReferenceId
        - createdAt
        - settlementWindow
        - settlementStartTime
      properties:
        object:
          readOnly: true
          type: string
          const: trade
          description: Resource type.
          example: trade
        id:
          $ref: '#/components/schemas/ResourceId'
          readOnly: true
          description: >-
            Unique identifier for this Trade. Readable, typed-prefix ID — see
            [Resource IDs](/v3/resource-ids).
          example: tde_5W7guYdHT24JFnRQrZN9y8
        quoteId:
          $ref: '#/components/schemas/ResourceId'
          readOnly: true
          description: References a `Quote.id` — the quote this trade was executed against.
          example: qte_3FfGK34vwMvVFDedyb2nkf
        buyCurrency:
          $ref: '#/components/schemas/CurrencyCode'
          readOnly: true
          description: Currency the user bought.
        sellCurrency:
          $ref: '#/components/schemas/CurrencyCode'
          readOnly: true
          description: Currency the user sold.
        buyAmount:
          $ref: '#/components/schemas/PositiveAmount'
          readOnly: true
          description: Present when the trade was specified in `buyCurrency` terms.
          example: '1000'
        sellAmount:
          $ref: '#/components/schemas/PositiveAmount'
          readOnly: true
          description: Present when the trade was specified in `sellCurrency` terms.
          example: '1000'
        executedAmount:
          $ref: '#/components/schemas/PositiveAmount'
          readOnly: true
          description: Final amount received in the counter-currency.
          example: '999.8'
        status:
          readOnly: true
          type: string
          description: Lifecycle state of the trade.
          example: EXECUTED
        clientReferenceId:
          readOnly: true
          oneOf:
            - type: string
            - type: 'null'
          description: Client-supplied reference for the trade, if any.
          example: order-123
        createdAt:
          $ref: '#/components/schemas/Timestamp'
          readOnly: true
          description: RFC 3339 timestamp at which the trade was created.
        settlementWindow:
          readOnly: true
          oneOf:
            - type: string
              enum:
                - IMMEDIATE
                - T0
                - T1
                - T2
            - type: 'null'
          description: Settlement window the trade settles in.
          example: T0
        settlementStartTime:
          readOnly: true
          oneOf:
            - $ref: '#/components/schemas/Timestamp'
            - type: 'null'
          description: RFC 3339 timestamp at which settlement started, or `null`.
          example: '2026-04-28T10:00:30.000Z'
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          description: The structured public error payload.
          required:
            - code
            - type
            - message
            - retryStrategy
            - details
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            type:
              $ref: '#/components/schemas/ErrorType'
            message:
              type: string
              description: >-
                Human-readable description. May change between versions; clients
                should switch on `code`, not `message`.
              example: The quoted rate has expired. Request a new quote.
            retryStrategy:
              $ref: '#/components/schemas/RetryStrategy'
            details:
              anyOf:
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_MISSING'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_INVALID'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_EXPIRED'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_INVALID_CONFIG'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_API_KEY_MISSING'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_API_KEY_INVALID'
                - $ref: >-
                    #/components/schemas/ErrorDetailsAUTH_API_KEY_SANDBOX_REQUIRED
                - $ref: '#/components/schemas/ErrorDetailsAUTH_API_KEY_LIVE_REQUIRED'
                - $ref: '#/components/schemas/ErrorDetailsSANDBOX_MODE_REQUIRED'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_FORBIDDEN_IP'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_INSUFFICIENT_SCOPE'
                - $ref: '#/components/schemas/ErrorDetailsFEATURE_NOT_ENABLED'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_QUERY_FAILED'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_PATH_FAILED'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_BODY_FAILED'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_CONTENT_TYPE'
                - $ref: >-
                    #/components/schemas/ErrorDetailsVALIDATION_PAYLOAD_TOO_LARGE
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_KEY_MISSING'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_KEY_INVALID'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_IN_FLIGHT'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_MISMATCH'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_UNAVAILABLE'
                - $ref: '#/components/schemas/ErrorDetailsROUTE_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsMETHOD_NOT_ALLOWED'
                - $ref: '#/components/schemas/ErrorDetailsRATE_LIMIT_EXCEEDED'
                - $ref: '#/components/schemas/ErrorDetailsINTERNAL_ERROR'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_NOT_REVERSIBLE'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_NOT_SETTLEABLE'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_NOT_MANUAL'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_ALREADY_SETTLED'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_EXECUTION_FAILED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsTRADE_DUPLICATE_CLIENT_REFERENCE
                - $ref: '#/components/schemas/ErrorDetailsTRADE_DISABLED'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_AMOUNT_ABOVE_LIMIT'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_AMOUNT_BELOW_MINIMUM'
                - $ref: >-
                    #/components/schemas/ErrorDetailsTRADE_PAIR_VOLUME_LIMIT_REACHED
                - $ref: '#/components/schemas/ErrorDetailsTRADE_CREDIT_LIMIT_EXCEEDED'
                - $ref: '#/components/schemas/ErrorDetailsTRADE_INSUFFICIENT_BALANCE'
                - $ref: >-
                    #/components/schemas/ErrorDetailsTRADE_CURRENCY_NOT_SUPPORTED
                - $ref: >-
                    #/components/schemas/ErrorDetailsTRADE_CURRENCY_NOT_ENABLED_FOR_ACCOUNT
                - $ref: '#/components/schemas/ErrorDetailsTRADE_PAIR_NOT_SUPPORTED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsTRADE_PAIR_NOT_ENABLED_FOR_ACCOUNT
                - $ref: '#/components/schemas/ErrorDetailsEXPOSURE_NOT_ENABLED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsQUOTE_INVALID_REFERENCE_UNIT
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_EXPIRED'
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_ALREADY_CONSUMED'
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsDEPOSIT_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsWITHDRAWAL_NOT_FOUND'
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_INITIATION_FAILED
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_INVALID_AMOUNT_PRECISION
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_INSUFFICIENT_BALANCE
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_ADDRESS_NOT_VERIFIED
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_ADDRESS_CHECKSUM_FAILED
                - $ref: '#/components/schemas/ErrorDetailsWITHDRAWAL_ACCOUNT_NOT_LIVE'
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_CURRENCY_NOT_SUPPORTED
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_DISABLED_FOR_ACCOUNT
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_PENDING_DEPOSIT_REQUIRED
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_ADDRESS_CURRENCY_MISMATCH
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_ADDRESS_NOT_FOUND
                - $ref: >-
                    #/components/schemas/ErrorDetailsWITHDRAWAL_ACCOUNT_FIAT_INVALID_NETWORK
              description: >-
                Closed, code-specific context. Use x-openfx-error-catalog to
                select the schema for error.code.
          additionalProperties: false
      additionalProperties: false
      description: >-
        Standard error response envelope returned for every non-successful API
        response.
    Timestamp:
      type: string
      format: date-time
      pattern: Z$
      description: UTC timestamp in RFC 3339 date-time form. Values end in Z.
      example: '2026-04-28T10:00:00.000Z'
    ResourceId:
      type: string
      pattern: ^[a-z]{3,5}_[1-9A-HJ-NP-Za-km-z]{1,22}$
      description: >-
        Readable resource identifier: a lowercase 3-to-5-letter type prefix
        (`qte_` Quote, `tde_` Trade, `dpt_` Deposit, `wtd_` Withdrawal, `wac_`
        WithdrawalAccount, `usr_` user/actor) followed by a Base58 (no
        `0`/`O`/`I`/`l`) encoding of the underlying 128-bit UUID. Body length is
        at most 22 characters and is not fixed — 21-22 for typical UUIDs,
        shorter only for near-zero values (the nil UUID encodes to 16). This
        pattern is a loose pre-filter; the authoritative check is a successful
        decode back to 16 bytes. Resolve back to the underlying UUID and object
        type with `GET /v3/display-ids`. See [Resource IDs](/v3/resource-ids).
      example: tde_5W7guYdHT24JFnRQrZN9y8
    CurrencyCode:
      type: string
      pattern: ^[A-Z0-9]{2,15}$
      description: >-
        Currency code. Fiat follows ISO 4217 (3 uppercase letters: `USD`, `EUR`,
        `GBP`). Stablecoins follow the canonical ticker (`USDC`, `USDT`,
        `EURC`). The format permits alphanumeric tickers (the regex allows
        digits).
      example: USDC
    PositiveAmount:
      type: string
      pattern: ^[0-9]+(\.[0-9]{1,8})?$
      description: >-
        Positive decimal amount as a string. Up to 8 fractional digits.
        Practical floor: 2 decimals for fiat, 6 for crypto. Used for **all**
        request body amount fields and for response/limit fields that are never
        negative (balances, withdrawal amounts, quote/trade amounts and rates,
        trade-limit error details). See [Amounts](/v3/amounts).


        Strings (not floats) to avoid IEEE-754 precision loss in JSON
        round-trips.
      example: '1000.00'
    ErrorCode:
      type: string
      description: >-
        Stable, machine-readable error code. Format `<PRODUCT>_<ERROR>`. Once
        published, never renamed or removed without a major version bump.
      enum:
        - AUTH_TOKEN_MISSING
        - AUTH_TOKEN_INVALID
        - AUTH_TOKEN_EXPIRED
        - AUTH_TOKEN_INVALID_CONFIG
        - AUTH_API_KEY_MISSING
        - AUTH_API_KEY_INVALID
        - AUTH_API_KEY_SANDBOX_REQUIRED
        - AUTH_API_KEY_LIVE_REQUIRED
        - SANDBOX_MODE_REQUIRED
        - AUTH_FORBIDDEN_IP
        - AUTH_INSUFFICIENT_SCOPE
        - FEATURE_NOT_ENABLED
        - VALIDATION_QUERY_FAILED
        - VALIDATION_PATH_FAILED
        - VALIDATION_BODY_FAILED
        - VALIDATION_CONTENT_TYPE
        - VALIDATION_PAYLOAD_TOO_LARGE
        - IDEMPOTENCY_KEY_MISSING
        - IDEMPOTENCY_KEY_INVALID
        - IDEMPOTENCY_IN_FLIGHT
        - IDEMPOTENCY_MISMATCH
        - IDEMPOTENCY_UNAVAILABLE
        - ROUTE_NOT_FOUND
        - METHOD_NOT_ALLOWED
        - RATE_LIMIT_EXCEEDED
        - INTERNAL_ERROR
        - TRADE_NOT_FOUND
        - TRADE_NOT_REVERSIBLE
        - TRADE_NOT_SETTLEABLE
        - TRADE_NOT_MANUAL
        - TRADE_ALREADY_SETTLED
        - TRADE_EXECUTION_FAILED
        - TRADE_DUPLICATE_CLIENT_REFERENCE
        - TRADE_DISABLED
        - TRADE_AMOUNT_ABOVE_LIMIT
        - TRADE_AMOUNT_BELOW_MINIMUM
        - TRADE_PAIR_VOLUME_LIMIT_REACHED
        - TRADE_CREDIT_LIMIT_EXCEEDED
        - TRADE_INSUFFICIENT_BALANCE
        - TRADE_CURRENCY_NOT_SUPPORTED
        - TRADE_CURRENCY_NOT_ENABLED_FOR_ACCOUNT
        - TRADE_PAIR_NOT_SUPPORTED
        - TRADE_PAIR_NOT_ENABLED_FOR_ACCOUNT
        - EXPOSURE_NOT_ENABLED
        - QUOTE_INVALID_REFERENCE_UNIT
        - QUOTE_EXPIRED
        - QUOTE_ALREADY_CONSUMED
        - QUOTE_NOT_FOUND
        - DEPOSIT_NOT_FOUND
        - WITHDRAWAL_NOT_FOUND
        - WITHDRAWAL_INITIATION_FAILED
        - WITHDRAWAL_INVALID_AMOUNT_PRECISION
        - WITHDRAWAL_INSUFFICIENT_BALANCE
        - WITHDRAWAL_ADDRESS_NOT_VERIFIED
        - WITHDRAWAL_ADDRESS_CHECKSUM_FAILED
        - WITHDRAWAL_ACCOUNT_NOT_LIVE
        - WITHDRAWAL_CURRENCY_NOT_SUPPORTED
        - WITHDRAWAL_DISABLED_FOR_ACCOUNT
        - WITHDRAWAL_PENDING_DEPOSIT_REQUIRED
        - WITHDRAWAL_ADDRESS_CURRENCY_MISMATCH
        - WITHDRAWAL_ADDRESS_NOT_FOUND
        - WITHDRAWAL_ACCOUNT_FIAT_INVALID_NETWORK
    ErrorType:
      type: string
      enum:
        - VALIDATION_ERROR
        - AUTHENTICATION_ERROR
        - AUTHORIZATION_ERROR
        - NOT_FOUND
        - CONFLICT
        - RATE_LIMITED
        - INTERNAL_ERROR
      description: >-
        Coarse error category for routing. Stable SCREAMING_SNAKE_CASE enum;
        clients may switch on this but must branch on `code` for specific
        handling, and default-handle unknown future values as `INTERNAL_ERROR`.
    RetryStrategy:
      type: string
      description: >-
        Machine-readable recovery hint, independent of `code` and `type`. Always
        present. Clients must default-handle unknown future values as
        `TERMINAL`.
      enum:
        - RETRY_SAME_KEY
        - WAIT_THEN_RETRY_SAME_KEY
        - FIX_AND_RESUBMIT
        - CHECK_STATE_THEN_RETRY
        - TERMINAL
    ErrorDetailsAUTH_TOKEN_MISSING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_TOKEN_MISSING`: The Authorization header is
        missing.
    ErrorDetailsAUTH_TOKEN_INVALID:
      type: object
      additionalProperties: false
      description: >-
        Optional diagnostic context for an invalid bearer token.
        Signature-verification and replay failures on the retained
        request-signing scheme fold into this code via `reason`; the field is
        omitted when it is not safe or useful to disclose.
      properties:
        reason:
          type: string
          enum:
            - SIGNATURE_INVALID
            - MALFORMED
            - DECODE_FAILED
            - REPLAYED
          description: Why the token was rejected. Optional.
          example: SIGNATURE_INVALID
    ErrorDetailsAUTH_TOKEN_EXPIRED:
      type: object
      additionalProperties: false
      properties:
        expiredAt:
          $ref: '#/components/schemas/Timestamp'
          description: Token expiry time in UTC.
      description: >-
        Structured context for `AUTH_TOKEN_EXPIRED`: The bearer token expiry
        time is in the past.
    ErrorDetailsAUTH_TOKEN_INVALID_CONFIG:
      type: object
      additionalProperties: false
      properties:
        reason:
          type: string
          description: Stable reason for the invalid token configuration.
        maxSeconds:
          type: string
          description: Maximum permitted validity window in seconds.
          pattern: ^[0-9]+$
      required:
        - reason
      description: >-
        Structured context for `AUTH_TOKEN_INVALID_CONFIG`: The bearer token
        claims or validity window violate the authentication contract.
    ErrorDetailsAUTH_API_KEY_MISSING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_MISSING`: The bearer token does not
        reference an API key.
    ErrorDetailsAUTH_API_KEY_INVALID:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_INVALID`: The referenced API key
        does not exist or is inactive.
    ErrorDetailsAUTH_API_KEY_SANDBOX_REQUIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_SANDBOX_REQUIRED`: Sandbox traffic
        uses a live API key.
    ErrorDetailsAUTH_API_KEY_LIVE_REQUIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_LIVE_REQUIRED`: Production traffic
        uses a sandbox API key.
    ErrorDetailsSANDBOX_MODE_REQUIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `SANDBOX_MODE_REQUIRED`: A sandbox request omits
        the required x-app-mode value.
    ErrorDetailsAUTH_FORBIDDEN_IP:
      type: object
      additionalProperties: false
      properties:
        ip:
          type: string
          description: >-
            The caller's IP, echoed for confirmation. Optional: production
            policy may suppress the offending IP, in which case this field is
            omitted.
          example: 203.0.113.42
      description: >-
        Structured context for `AUTH_FORBIDDEN_IP`: The source IP address is
        outside the API key allowlist.
    ErrorDetailsAUTH_INSUFFICIENT_SCOPE:
      type: object
      required:
        - requiredScope
      additionalProperties: false
      properties:
        requiredScope:
          type: string
          description: Scope the API key would need to grant this request.
          example: trade
      description: >-
        Structured context for `AUTH_INSUFFICIENT_SCOPE`: The API key lacks a
        scope required by the operation.
    ErrorDetailsFEATURE_NOT_ENABLED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `FEATURE_NOT_ENABLED`: The caller's organization
        is not enabled for this feature.
    ErrorDetailsVALIDATION_QUERY_FAILED:
      $ref: '#/components/schemas/ValidationIssues'
      description: >-
        Structured context for `VALIDATION_QUERY_FAILED`: One or more query
        parameters fail schema validation.
    ErrorDetailsVALIDATION_PATH_FAILED:
      $ref: '#/components/schemas/ValidationIssues'
      description: >-
        Structured context for `VALIDATION_PATH_FAILED`: One or more path
        parameters fail schema validation.
    ErrorDetailsVALIDATION_BODY_FAILED:
      $ref: '#/components/schemas/ValidationIssues'
      description: >-
        Structured context for `VALIDATION_BODY_FAILED`: The request body fails
        schema validation.
    ErrorDetailsVALIDATION_CONTENT_TYPE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `VALIDATION_CONTENT_TYPE`: The request's
        Content-Type is not application/json, or specifies an unsupported
        charset.
    ErrorDetailsVALIDATION_PAYLOAD_TOO_LARGE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `VALIDATION_PAYLOAD_TOO_LARGE`: The request body
        exceeds the maximum allowed payload size.
    ErrorDetailsIDEMPOTENCY_KEY_MISSING:
      type: object
      required:
        - endpoint
      additionalProperties: false
      properties:
        endpoint:
          type: string
          description: Endpoint path that requires the header.
          example: /v3/fx/trades
      description: >-
        Structured context for `IDEMPOTENCY_KEY_MISSING`: A write request omits
        the Idempotency-Key header.
    ErrorDetailsIDEMPOTENCY_KEY_INVALID:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `IDEMPOTENCY_KEY_INVALID`: The Idempotency-Key
        value does not match ^[a-zA-Z0-9_-]{1,255}$.
    ErrorDetailsIDEMPOTENCY_IN_FLIGHT:
      allOf:
        - $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `IDEMPOTENCY_IN_FLIGHT`: Another request with the
        same idempotency key is still processing.
    ErrorDetailsIDEMPOTENCY_MISMATCH:
      type: object
      required:
        - originalRequestHash
      additionalProperties: false
      properties:
        originalRequestHash:
          type: string
          pattern: ^sha256:[a-f0-9]{64}$
          description: >-
            Stable hash of the request body the key was first seen with. Lets
            clients confirm which prior request collides with the current one
            without exposing the original payload.
          example: >-
            sha256:9b74c9897bac770ffc029102a200c5de9f73b4e7c8a1d4f8e3a9b2c6e5f7a8d2
      description: >-
        Structured context for `IDEMPOTENCY_MISMATCH`: An idempotency key is
        reused with a different request body.
    ErrorDetailsIDEMPOTENCY_UNAVAILABLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `IDEMPOTENCY_UNAVAILABLE`: The idempotency
        service is temporarily unreachable, so the request's Idempotency-Key
        could not be checked.
    ErrorDetailsROUTE_NOT_FOUND:
      type: object
      additionalProperties: false
      properties:
        path:
          type: string
          description: Requested URL path.
          pattern: ^/
      required:
        - path
      description: >-
        Structured context for `ROUTE_NOT_FOUND`: The request path does not
        match a v3 route.
    ErrorDetailsMETHOD_NOT_ALLOWED:
      type: object
      additionalProperties: false
      properties:
        method:
          type: string
          description: Rejected HTTP method.
        allowed:
          type: array
          description: HTTP methods supported by the requested path.
          minItems: 1
          uniqueItems: true
          items:
            type: string
            description: Supported HTTP method.
      required:
        - method
        - allowed
      description: >-
        Structured context for `METHOD_NOT_ALLOWED`: The HTTP method is not
        supported on the request path.
    ErrorDetailsRATE_LIMIT_EXCEEDED:
      allOf:
        - $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `RATE_LIMIT_EXCEEDED`: The organization or API
        key exceeds its request limit.
    ErrorDetailsINTERNAL_ERROR:
      type: object
      additionalProperties: false
      properties:
        resourceId:
          $ref: '#/components/schemas/ResourceId'
          description: >-
            Optional. Present only when a server failure occurred on a
            money-movement write that may have created or mutated a resource;
            when present, the client should `GET` the resource by this ID before
            retrying. Absent for read-path failures (retry with backoff).
          example: tde_5W7guYdHT24JFnRQrZN9y8
      description: >-
        Structured context for `INTERNAL_ERROR`: An unclassified server-side
        failure occurs.
    ErrorDetailsTRADE_NOT_FOUND:
      type: object
      required:
        - tradeId
      additionalProperties: false
      properties:
        tradeId:
          $ref: '#/components/schemas/ResourceId'
          description: ID requested by the client.
          example: tde_5W7guYdHT24JFnRQrZN9y8
      description: >-
        Structured context for `TRADE_NOT_FOUND`: The trade identifier is
        unknown or inaccessible to the caller.
    ErrorDetailsTRADE_NOT_REVERSIBLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `TRADE_NOT_REVERSIBLE`: The trade is outside its
        reversal window or has already been reversed or settled.
    ErrorDetailsTRADE_NOT_SETTLEABLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `TRADE_NOT_SETTLEABLE`: The trade isn't in a
        settleable state (already settled, not yet executed, or reversed).
    ErrorDetailsTRADE_NOT_MANUAL:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `TRADE_NOT_MANUAL`: The trade is not a manual
        trade and cannot be settled through this endpoint.
    ErrorDetailsTRADE_ALREADY_SETTLED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `TRADE_ALREADY_SETTLED`: The trade has already
        been settled.
    ErrorDetailsTRADE_EXECUTION_FAILED:
      $ref: '#/components/schemas/ResourceCheckProbe'
      description: >-
        Structured context for `TRADE_EXECUTION_FAILED`: Trade execution fails
        after the write is accepted.
    ErrorDetailsTRADE_DUPLICATE_CLIENT_REFERENCE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `TRADE_DUPLICATE_CLIENT_REFERENCE`: A trade
        already exists with the given clientReferenceId.
    ErrorDetailsTRADE_DISABLED:
      description: >-
        No structured context. Trading access has been disabled by OpenFX; the
        reason is not exposed in `details`. Returns `{}`.
      allOf:
        - $ref: '#/components/schemas/EmptyErrorDetails'
    ErrorDetailsTRADE_AMOUNT_ABOVE_LIMIT:
      type: object
      required:
        - requestedAmount
        - currency
        - limitAmount
      additionalProperties: false
      properties:
        requestedAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Submitted amount, denominated in `currency`.
          example: '1000000.00'
        currency:
          $ref: '#/components/schemas/CurrencyCode'
        limitAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Configured maximum, denominated in `currency`.
          example: '500000.00'
      description: >-
        Structured context for `TRADE_AMOUNT_ABOVE_LIMIT`: The trade amount
        exceeds the organization's maximum.
    ErrorDetailsTRADE_AMOUNT_BELOW_MINIMUM:
      type: object
      required:
        - requestedAmount
        - currency
        - minimumAmount
      additionalProperties: false
      properties:
        requestedAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Submitted amount, denominated in `currency`.
          example: '1.00'
        currency:
          $ref: '#/components/schemas/CurrencyCode'
        minimumAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Configured minimum, denominated in `currency`.
          example: '10.00'
      description: >-
        Structured context for `TRADE_AMOUNT_BELOW_MINIMUM`: The trade amount is
        below the organization's minimum.
    ErrorDetailsTRADE_PAIR_VOLUME_LIMIT_REACHED:
      type: object
      additionalProperties: false
      properties:
        pair:
          type: string
          description: Currency pair symbol.
      required:
        - pair
      description: >-
        Structured context for `TRADE_PAIR_VOLUME_LIMIT_REACHED`: The currency
        pair reaches its global net-position limit.
    ErrorDetailsTRADE_CREDIT_LIMIT_EXCEEDED:
      type: object
      additionalProperties: false
      properties:
        usedAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Credit currently in use.
        limitAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Maximum permitted credit.
        currency:
          $ref: '#/components/schemas/CurrencyCode'
          description: ISO 4217 currency code.
      required:
        - usedAmount
        - limitAmount
        - currency
      description: >-
        Structured context for `TRADE_CREDIT_LIMIT_EXCEEDED`: The trade would
        exceed the organization's credit limit.
    ErrorDetailsTRADE_INSUFFICIENT_BALANCE:
      type: object
      required:
        - requiredAmount
        - availableAmount
        - currency
        - side
      additionalProperties: false
      properties:
        requiredAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Amount required to execute the trade, denominated in `currency`.
          example: '1000.00'
        availableAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Currently available balance, denominated in `currency`.
          example: '250.00'
        currency:
          $ref: '#/components/schemas/CurrencyCode'
        side:
          type: string
          enum:
            - BUY
            - SELL
          description: >-
            Which side of the trade came up short. The sell-side balance is
            checked at execute time; the value is included on every emission so
            clients can branch without re-deriving it.
          example: SELL
      description: >-
        Structured context for `TRADE_INSUFFICIENT_BALANCE`: The sell-side
        balance is insufficient at execution time.
    ErrorDetailsTRADE_CURRENCY_NOT_SUPPORTED:
      type: object
      required:
        - currency
      additionalProperties: false
      properties:
        currency:
          $ref: '#/components/schemas/CurrencyCode'
          description: The unsupported currency code.
      description: >-
        Structured context for `TRADE_CURRENCY_NOT_SUPPORTED`: The requested
        currency is not supported.
    ErrorDetailsTRADE_CURRENCY_NOT_ENABLED_FOR_ACCOUNT:
      type: object
      additionalProperties: false
      properties:
        currency:
          $ref: '#/components/schemas/CurrencyCode'
          description: ISO 4217 currency code.
      required:
        - currency
      description: >-
        Structured context for `TRADE_CURRENCY_NOT_ENABLED_FOR_ACCOUNT`: The
        requested currency is not enabled for the organization.
    ErrorDetailsTRADE_PAIR_NOT_SUPPORTED:
      type: object
      required:
        - pair
      additionalProperties: false
      properties:
        pair:
          type: string
          description: The requested pair identifier (`SELL_BUY`).
          example: USDC_ZAR
      description: >-
        Structured context for `TRADE_PAIR_NOT_SUPPORTED`: The requested
        currency pair is not supported.
    ErrorDetailsTRADE_PAIR_NOT_ENABLED_FOR_ACCOUNT:
      type: object
      additionalProperties: false
      properties:
        pair:
          type: string
          description: Currency pair symbol.
      required:
        - pair
      description: >-
        Structured context for `TRADE_PAIR_NOT_ENABLED_FOR_ACCOUNT`: The
        requested currency pair is not enabled for the organization.
    ErrorDetailsEXPOSURE_NOT_ENABLED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `EXPOSURE_NOT_ENABLED`: No credit exposure limit
        is configured for the organization.
    ErrorDetailsQUOTE_INVALID_REFERENCE_UNIT:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `QUOTE_INVALID_REFERENCE_UNIT`: The reference
        unit does not match either currency in the requested pair.
    ErrorDetailsQUOTE_EXPIRED:
      type: object
      required:
        - quoteId
        - expiredAt
      additionalProperties: false
      properties:
        quoteId:
          $ref: '#/components/schemas/ResourceId'
          description: ID of the quote that has expired.
          example: qte_3FfGK34vwMvVFDedyb2nkf
        expiredAt:
          description: Instant at which the quote expired.
          allOf:
            - $ref: '#/components/schemas/Timestamp'
          example: '2026-04-28T10:00:00.000Z'
      description: >-
        Structured context for `QUOTE_EXPIRED`: The quote expires before trade
        execution.
    ErrorDetailsQUOTE_ALREADY_CONSUMED:
      type: object
      required:
        - quoteId
        - consumedAt
      additionalProperties: false
      properties:
        quoteId:
          $ref: '#/components/schemas/ResourceId'
          description: >-
            ID of the quote that has already been consumed by a prior successful
            trade. Quotes are single-use.
          example: qte_3FfGK34vwMvVFDedyb2nkf
        consumedAt:
          description: Instant at which the quote was first consumed.
          allOf:
            - $ref: '#/components/schemas/Timestamp'
          example: '2026-04-28T10:00:01.000Z'
      description: >-
        Structured context for `QUOTE_ALREADY_CONSUMED`: The quote was consumed
        by an earlier successful trade.
    ErrorDetailsQUOTE_NOT_FOUND:
      type: object
      additionalProperties: false
      properties:
        quoteId:
          $ref: '#/components/schemas/ResourceId'
          description: Quote identifier.
      required:
        - quoteId
      description: >-
        Structured context for `QUOTE_NOT_FOUND`: The quote identifier is
        unknown or inaccessible to the caller.
    ErrorDetailsDEPOSIT_NOT_FOUND:
      type: object
      required:
        - depositId
      additionalProperties: false
      properties:
        depositId:
          $ref: '#/components/schemas/ResourceId'
          description: ID requested by the client.
          example: dpt_EA9vbVngB76PmMibCiMNPb
      description: >-
        Structured context for `DEPOSIT_NOT_FOUND`: The deposit identifier is
        unknown or inaccessible to the caller.
    ErrorDetailsWITHDRAWAL_NOT_FOUND:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `WITHDRAWAL_NOT_FOUND`: The withdrawal identifier
        is unknown or inaccessible to the caller.
    ErrorDetailsWITHDRAWAL_INITIATION_FAILED:
      $ref: '#/components/schemas/ResourceCheckProbe'
      description: >-
        Structured context for `WITHDRAWAL_INITIATION_FAILED`: Withdrawal
        initiation fails after the write is accepted.
    ErrorDetailsWITHDRAWAL_INVALID_AMOUNT_PRECISION:
      type: object
      required:
        - maxDecimals
        - currency
      additionalProperties: false
      properties:
        maxDecimals:
          type: integer
          minimum: 0
          description: Maximum fractional digits allowed for `currency`.
          example: 2
        currency:
          $ref: '#/components/schemas/CurrencyCode'
      description: >-
        Structured context for `WITHDRAWAL_INVALID_AMOUNT_PRECISION`: The
        withdrawal amount exceeds the currency's decimal precision.
    ErrorDetailsWITHDRAWAL_INSUFFICIENT_BALANCE:
      type: object
      required:
        - requiredAmount
        - availableAmount
        - currency
      additionalProperties: false
      properties:
        requiredAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Amount required for the withdrawal, denominated in `currency`.
          example: '1000.00'
        availableAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Currently available balance, denominated in `currency`.
          example: '250.00'
        currency:
          $ref: '#/components/schemas/CurrencyCode'
      description: >-
        Structured context for `WITHDRAWAL_INSUFFICIENT_BALANCE`: The available
        balance is lower than the withdrawal amount.
    ErrorDetailsWITHDRAWAL_ADDRESS_NOT_VERIFIED:
      type: object
      additionalProperties: false
      properties:
        accountId:
          $ref: '#/components/schemas/ResourceId'
          description: Withdrawal account identifier.
      required:
        - accountId
      description: >-
        Structured context for `WITHDRAWAL_ADDRESS_NOT_VERIFIED`: The
        destination account is inactive or unverified.
    ErrorDetailsWITHDRAWAL_ADDRESS_CHECKSUM_FAILED:
      type: object
      additionalProperties: false
      properties:
        address:
          type: string
          description: Rejected on-chain address.
        network:
          type: string
          description: Blockchain network used to validate the address.
      required:
        - address
        - network
      description: >-
        Structured context for `WITHDRAWAL_ADDRESS_CHECKSUM_FAILED`: The
        destination address checksum is invalid for the selected network.
    ErrorDetailsWITHDRAWAL_ACCOUNT_NOT_LIVE:
      type: object
      additionalProperties: false
      properties:
        accountId:
          $ref: '#/components/schemas/ResourceId'
          description: Withdrawal account identifier.
        status:
          type: string
          description: Current withdrawal-account lifecycle status.
      required:
        - accountId
        - status
      description: >-
        Structured context for `WITHDRAWAL_ACCOUNT_NOT_LIVE`: The destination
        withdrawal account is not active.
    ErrorDetailsWITHDRAWAL_CURRENCY_NOT_SUPPORTED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `WITHDRAWAL_CURRENCY_NOT_SUPPORTED`: The
        requested currency is not supported for withdrawals.
    ErrorDetailsWITHDRAWAL_DISABLED_FOR_ACCOUNT:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `WITHDRAWAL_DISABLED_FOR_ACCOUNT`: Withdrawals
        are currently disabled for the caller's account.
    ErrorDetailsWITHDRAWAL_PENDING_DEPOSIT_REQUIRED:
      type: object
      additionalProperties: false
      properties:
        outstandingAmount:
          $ref: '#/components/schemas/PositiveAmount'
          description: Outstanding settlement amount.
        currency:
          $ref: '#/components/schemas/CurrencyCode'
          description: ISO 4217 currency code.
      required:
        - outstandingAmount
        - currency
      description: >-
        Structured context for `WITHDRAWAL_PENDING_DEPOSIT_REQUIRED`: An
        outstanding settlement deposit must be paid first.
    ErrorDetailsWITHDRAWAL_ADDRESS_CURRENCY_MISMATCH:
      type: object
      required:
        - expected
        - received
      additionalProperties: false
      properties:
        expected:
          $ref: '#/components/schemas/CurrencyCode'
          description: Currency the withdrawal account is configured for.
        received:
          $ref: '#/components/schemas/CurrencyCode'
          description: Currency submitted in the request body.
      description: >-
        Structured context for `WITHDRAWAL_ADDRESS_CURRENCY_MISMATCH`: The
        request currency differs from the destination account currency.
    ErrorDetailsWITHDRAWAL_ADDRESS_NOT_FOUND:
      type: object
      required:
        - accountId
      additionalProperties: false
      properties:
        accountId:
          $ref: '#/components/schemas/ResourceId'
          description: The `accountId` that could not be resolved.
          example: wac_NDqQ9LmcUASpnHR6CTvdkk
      description: >-
        Structured context for `WITHDRAWAL_ADDRESS_NOT_FOUND`: The destination
        account identifier is unknown or inaccessible to the caller.
    ErrorDetailsWITHDRAWAL_ACCOUNT_FIAT_INVALID_NETWORK:
      type: object
      required:
        - network
      additionalProperties: false
      properties:
        network:
          type: string
          description: >-
            The `network` value that was rejected because it was combined with
            `assetType=FIAT`.
          example: ETHEREUM
      description: >-
        Structured context for `WITHDRAWAL_ACCOUNT_FIAT_INVALID_NETWORK`: The
        `network` filter was supplied together with `assetType=FIAT`, which has
        no network.
    EmptyErrorDetails:
      type: object
      description: Closed details object for errors that expose no additional context.
      additionalProperties: false
      maxProperties: 0
    ValidationIssues:
      type: object
      required:
        - issues
      additionalProperties: false
      description: >-
        Structured `details` shape shared by `VALIDATION_QUERY_FAILED`,
        `VALIDATION_PATH_FAILED`, and `VALIDATION_BODY_FAILED`.
      properties:
        issues:
          type: array
          description: One entry per failing field.
          items:
            $ref: '#/components/schemas/ValidationIssue'
        firstIssuePath:
          type: string
          description: >-
            JSON Pointer (RFC 6901) to the first failing field, for clients that
            only surface one error at a time. Optional.
          example: /amount
    ResourceCheckProbe:
      type: object
      required:
        - resourceId
      additionalProperties: false
      description: >-
        Details echoed on indeterminate-write 500s (`TRADE_EXECUTION_FAILED`,
        `WITHDRAWAL_INITIATION_FAILED`). The write may or may not have
        persisted: `GET` the resource by `resourceId` and treat a found resource
        as success before retrying.
      properties:
        resourceId:
          $ref: '#/components/schemas/ResourceId'
          description: >-
            ID of the resource the client should `GET` to determine whether the
            write persisted before retrying.
          example: tde_5W7guYdHT24JFnRQrZN9y8
        timeoutMs:
          type: integer
          minimum: 0
          description: >-
            Upstream timeout, in milliseconds, when the failure was a timeout.
            Optional.
          example: 30000
    ValidationIssue:
      type: object
      required:
        - path
        - code
        - message
      additionalProperties: false
      properties:
        path:
          type: string
          description: >-
            JSON Pointer (RFC 6901) to the failing field (e.g. `/amount` or
            `/items/0/currency`).
          example: /amount
        code:
          type: string
          description: >-
            Stable validator code (e.g. `invalid_type`, `invalid_string`,
            `too_small`).
          example: invalid_type
        message:
          type: string
          description: Human-readable description of the failure.
          example: Expected string, received number
        expected:
          type: string
          description: Expected value or type, when the validator reports one. Optional.
          example: string
        received:
          type: string
          description: Received value or type, when the validator reports one. Optional.
          example: number
      description: >-
        One validation issue associated with a request field, parameter, or
        body.
  parameters:
    XRequestId:
      name: X-Request-Id
      in: header
      required: false
      description: >-
        Optional, client-supplied correlation ID for this request. Echoed
        verbatim on the response when supplied; the response omits it when the
        request did not supply one. Distinct from `X-Trace-Id`
        (server-generated, always present). See [Metadata &
        tracing](/v3/metadata-and-tracing#client-request-correlation).
      schema:
        type: string
        example: my-req-abc-123
  headers:
    XTraceId:
      description: OpenFX trace ID for support and debugging correlation.
      schema:
        type: string
      example: 4bf92f3577b34da6a3ce929d0e0e4736
    XRequestId:
      description: >-
        Client-supplied correlation ID, echoed verbatim. Present only when the
        request included `X-Request-Id`.
      schema:
        type: string
      example: my-req-abc-123
    XRequestTimestamp:
      description: >-
        Server UTC timestamp of when the request reached the API service. RFC
        3339 / ISO 8601 with millisecond precision.
      schema:
        $ref: '#/components/schemas/Timestamp'
      example: '2026-05-29T12:34:56.789Z'
    RateLimitLimit:
      description: Maximum requests allowed in the current window.
      schema:
        type: integer
      example: 30
    RateLimitReset:
      description: >-
        Seconds until the current rate-limit window resets (a duration, counted
        from the response time — not an absolute Unix timestamp).
      schema:
        type: integer
      example: 8
    Allow:
      description: >-
        Comma-separated list of HTTP methods supported on the requested path.
        Sent with 405 responses (RFC 9110).
      schema:
        type: string
      example: GET
    RetryAfter:
      description: >-
        Seconds to wait before retrying. Present on `429 RATE_LIMIT_EXCEEDED`
        and `409 IDEMPOTENCY_IN_FLIGHT` responses only.
      schema:
        type: integer
      example: 10
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        ES256-signed JWT bearer token, single-use, 60-second TTL. See
        [Authentication](/v3/authentication) for how to mint one.
    requestSignatureAuth:
      type: apiKey
      in: header
      name: X-Request-Signature
      description: >-
        ES256 signature over the request, bound to the bearer JWT. Required on
        every v3 request. See [Authentication → Request
        signing](/v3/authentication#request-signing).

````