openapi: "3.0.3"
info:
  title: Swift Community FX API
  description: >
    The Debtor Agent (DA) to Gateway Intermediary (GI) pre-payment quoting interface for the Swift payments scheme.
    DA banks call this API to obtain a locked FX rate from a GI (Gateway
    Intermediary) before constructing the pacs.008.
  version: "1.0.0"
  contact:
    name: Developer Hub
    url: https://developer.swift.com
    email: developer-support@swift.com
  license:
    name: Community API Redistribution License
    url: https://www.swift.com/swift-resource/251146/download

servers:
  - url: https://sandbox.swift.com/swift/community-fx/v1
    description: Sandbox environment
  - url: https://api-test.swiftnet.sipn.swift.com/swift/community-fx/v1
    description: Pilot environment
  - url: https://api.swiftnet.sipn.swift.com/swift/community-fx/v1
    description: Production environment

externalDocs:
  description: |
    To make a request to this API, the client must pass the access token obtained as a result of OAuth 2.0 flows. For more information please visit the developer portal.
  url: https://developer.swift.com

security:
  - oauthBearerToken: []

tags:
  - name: FX Quotes
    description: FX quoting, rate locking, and fee transparency for the DA-to-GI pre-payment quoting flow.
  - name: Corridors
    description: Provider corridor coverage declaration (feeds the separate Swift scheme eligibility API)


paths:
  /quotes:
    post:
      operationId: createQuote
      summary: Request an FX quote
      description: >
        Submit a request for one or more FX quotes. Specify source or
        destination amount mode. Use instrument_type=all to receive quotes
        for every valid instrument combination. The response contains at
        most 20 quotes. To compare all options, start with
        instrument_type=all, then narrow with specific values if needed.
      tags:
        - FX Quotes
      parameters:
        - $ref: "#/components/parameters/X-BIC"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/FxQuoteRequest"
            examples:
              b2b_source_amount_bank_account:
                summary: B2B salary payment, source amount mode, single instrument
                description: |
                  DA bank wants to convert exactly 500 USD to COP for a business salary payment via bank account.
                  Uses idempotency_key for safe retries. This is the most common B2B pattern.
                value:
                  source_currency: "USD"
                  destination_currency: "COP"
                  source_amount: "500.00"
                  instrument_type: "bank_account"
                  transaction_type: "b2b"
                  purpose_code: "SALA"
                  instructing_agent_bic: "FXDAUS33XXX"
                  idempotency_key: "a3b1c8d0-7f4e-4a1b-9c6d-e2f5a8b0d1c4"
              p2p_destination_amount_mobile_wallet:
                summary: P2P remittance, destination amount mode, mobile wallet
                description: |
                  Sender wants the recipient to receive exactly 2,000,000 COP via mobile wallet.
                  The GI calculates the required source_amount based on the current rate.
                  This is the typical retail remittance pattern for emerging market corridors.
                value:
                  source_currency: "USD"
                  destination_currency: "COP"
                  destination_amount: "2000000.00"
                  instrument_type: "mobile_wallet"
                  transaction_type: "p2p"
                  instructing_agent_bic: "FXDAUS33XXX"
              multi_quote_all_instruments:
                summary: Comparison shopping â€” all instruments and settlement options
                description: |
                  DA requests quotes for every valid instrument combination on this corridor.
                  The GI returns multiple quotes in the response array, each with a different
                  instrument_type and potentially different rates, fees, and delivery times.
                  The DA presents these options to the sender for selection.
                value:
                  source_currency: "USD"
                  destination_currency: "COP"
                  source_amount: "500.00"
                  instrument_type: "all"
                  transaction_type: "b2b"
                  purpose_code: "SALA"
                  instructing_agent_bic: "FXDAUS33XXX"
      responses:
        "200":
          description: FX quote(s) created
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                type: object
                required:
                  - quotes
                properties:
                  quotes:
                    type: array
                    maxItems: 20
                    items:
                      $ref: "#/components/schemas/FxQuote"
              examples:
                single_quote_b2b_bank_account:
                  summary: Single B2B quote via bank account (source amount mode)
                  description: |
                    Response to b2b_source_amount_bank_account request. One quote returned for
                    bank_account instrument. Note estimated_delivery shows a sender-facing string
                    and estimated_delivery_duration provides the machine-readable ISO 8601 duration.
                  value:
                    quotes:
                      - quote_id: "q-12345-abcde"
                        source_currency: "USD"
                        destination_currency: "COP"
                        fx_rate: "4152.3500000000"
                        source_amount: "500.00"
                        destination_amount: "2076175.00"
                        expires_at: "2025-01-15T10:35:00Z"
                        created_at: "2025-01-15T10:32:00Z"
                        ttl_seconds: 300
                        instrument_type: "bank_account"
                        transaction_type: "b2b"
                        settlement_type: "spot"
                        estimated_delivery: "2025-09-09T10:35:15.000Z"
                        estimated_delivery_duration: "P2D"
                        value_date: "2025-01-17"
                        conversion_fee:
                          amount: "5.00"
                          currency: "USD"
                        charge_type: "DEBT"
                        total_debit_amount:
                          amount: "505.00"
                          currency: "USD"
                        min_amount: "10.00"
                        max_amount: "50000.00"
                        scheme: "swift_cfx"
                        status: "active"
                multi_quote_all_instruments:
                  summary: Multiple quotes for instrument_type=all
                  description: |
                    Response to multi_quote_all_instruments request. The GI returns one quote per
                    valid instrument on this corridor. Each has different rates, fees, delivery
                    times, and settlement models. The DA presents these to the sender for comparison.
                  value:
                    quotes:
                      - quote_id: "q-12345-abcde"
                        source_currency: "USD"
                        destination_currency: "COP"
                        fx_rate: "4152.3500000000"
                        source_amount: "500.00"
                        destination_amount: "2076175.00"
                        expires_at: "2025-01-15T10:35:00Z"
                        created_at: "2025-01-15T10:32:00Z"
                        ttl_seconds: 300
                        instrument_type: "bank_account"
                        transaction_type: "b2b"
                        settlement_type: "spot"
                        estimated_delivery: "2025-09-09T10:35:15.000Z"
                        estimated_delivery_duration: "P2D"
                        value_date: "2025-01-17"
                        conversion_fee:
                          amount: "5.00"
                          currency: "USD"
                        charge_type: "DEBT"
                        total_debit_amount:
                          amount: "505.00"
                          currency: "USD"
                        min_amount: "10.00"
                        max_amount: "50000.00"
                        scheme: "swift_cfx"
                        status: "active"
                      - quote_id: "q-12345-fghij"
                        source_currency: "USD"
                        destination_currency: "COP"
                        fx_rate: "4148.7000000000"
                        source_amount: "500.00"
                        destination_amount: "2074350.00"
                        expires_at: "2025-01-15T10:35:00Z"
                        created_at: "2025-01-15T10:32:00Z"
                        ttl_seconds: 300
                        instrument_type: "mobile_wallet"
                        transaction_type: "b2b"
                        settlement_type: "inst"
                        estimated_delivery: "2025-09-09T10:35:15.000Z"
                        estimated_delivery_duration: "PT30M"
                        conversion_fee:
                          amount: "7.50"
                          currency: "USD"
                        charge_type: "DEBT"
                        total_debit_amount:
                          amount: "507.50"
                          currency: "USD"
                        min_amount: "5.00"
                        max_amount: "10000.00"
                        scheme: "swift_cfx"
                        status: "active"
        "400":
          description: Bad Request
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Mutually_Exclusive_Amounts:
                  $ref: "#/components/examples/BadRequest_MutuallyExclusiveAmounts"
                Missing_Required_Field:
                  $ref: "#/components/examples/BadRequest_MissingRequiredField"
                Invalid_BIC:
                  $ref: "#/components/examples/BadRequest_InvalidBIC"
                Missing_Amount:
                  $ref: "#/components/examples/BadRequest_MissingAmount"
        "401":
          description: Unauthorized
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Invalid_Token:
                  $ref: "#/components/examples/InvalidToken"
                Inconsistent_Client:
                  $ref: "#/components/examples/InconsistentClient"
        "403":
          description: Forbidden
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Insufficient_Scope:
                  $ref: "#/components/examples/InsufficientScope"
        "404":
          description: Not Found
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Resource_Not_Found:
                  $ref: "#/components/examples/ResourceNotFound"
        "429":
          description: Too Many Requests
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Rate_Limit_Exceeded:
                  $ref: "#/components/examples/RateLimitExceeded"
        "503":
          description: Service Unavailable
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Unavailable:
                  $ref: "#/components/examples/ProviderUnavailable"
                Provider_Maintenance:
                  $ref: "#/components/examples/ProviderMaintenance"
        "504":
          description: Gateway Timeout
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Timeout:
                  $ref: "#/components/examples/ProviderTimeout"

  /quotes/{quote_id}:
    get:
      operationId: getQuote
      summary: Retrieve a specific FX quote
      description: >
        Retrieve a previously created quote by its ID. Returns the quote with
        current status (active or expired).
      tags:
        - FX Quotes
      parameters:
        - $ref: "#/components/parameters/X-BIC"
        - name: quote_id
          in: path
          required: true
          schema:
            type: string
            maxLength: 36
          example: "q-12345-abcde"
      responses:
        "200":
          description: Quote retrieved
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FxQuote"
              examples:
                active_quote:
                  summary: Active quote with remaining validity
                  description: |
                    The quote is still within its validity window. ttl_seconds shows the remaining
                    time (180s = 3 minutes left). The DA can proceed with authorisation.
                  value:
                    quote_id: "q-12345-abcde"
                    source_currency: "USD"
                    destination_currency: "COP"
                    fx_rate: "4152.3500000000"
                    source_amount: "500.00"
                    destination_amount: "2076175.00"
                    expires_at: "2025-01-15T10:35:00Z"
                    created_at: "2025-01-15T10:32:00Z"
                    ttl_seconds: 180
                    instrument_type: "bank_account"
                    transaction_type: "b2b"
                    settlement_type: "spot"
                    estimated_delivery: "2025-09-09T10:35:15.000Z"
                    estimated_delivery_duration: "P2D"
                    value_date: "2025-01-17"
                    conversion_fee:
                      amount: "5.00"
                      currency: "USD"
                    charge_type: "DEBT"
                    total_debit_amount:
                      amount: "505.00"
                      currency: "USD"
                    min_amount: "10.00"
                    max_amount: "50000.00"
                    scheme: "swift_cfx"
                    status: "active"
                expired_quote:
                  summary: Expired quote â€” rate no longer valid
                  description: |
                    The quote has passed its expires_at time. ttl_seconds is 0. The DA must request
                    a new quote via POST /quotes. The rate and amounts are historical â€” they show
                    what was offered, but the GI will not honor them.
                  value:
                    quote_id: "q-12345-abcde"
                    source_currency: "USD"
                    destination_currency: "COP"
                    fx_rate: "4152.3500000000"
                    source_amount: "500.00"
                    destination_amount: "2076175.00"
                    expires_at: "2025-01-15T10:35:00Z"
                    created_at: "2025-01-15T10:32:00Z"
                    ttl_seconds: 0
                    instrument_type: "bank_account"
                    transaction_type: "b2b"
                    settlement_type: "spot"
                    estimated_delivery: "2025-09-09T10:35:15.000Z"
                    estimated_delivery_duration: "P2D"
                    value_date: "2025-01-17"
                    conversion_fee:
                      amount: "5.00"
                      currency: "USD"
                    charge_type: "DEBT"
                    total_debit_amount:
                      amount: "505.00"
                      currency: "USD"
                    min_amount: "10.00"
                    max_amount: "50000.00"
                    scheme: "swift_cfx"
                    status: "expired"
        "400":
          description: Bad Request
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Invalid_Parameter_Format:
                  $ref: "#/components/examples/BadRequest_InvalidParameterFormat"
        "401":
          description: Unauthorized
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Invalid_Token:
                  $ref: "#/components/examples/InvalidToken"
                Inconsistent_Client:
                  $ref: "#/components/examples/InconsistentClient"
        "403":
          description: Forbidden
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Insufficient_Scope:
                  $ref: "#/components/examples/InsufficientScope"
        "404":
          description: Not Found
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Quote_Not_Found:
                  $ref: "#/components/examples/QuoteNotFound"
        "429":
          description: Too Many Requests
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Rate_Limit_Exceeded:
                  $ref: "#/components/examples/RateLimitExceeded"
        "503":
          description: Service Unavailable
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Unavailable:
                  $ref: "#/components/examples/ProviderUnavailable"
        "504":
          description: Gateway Timeout
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Timeout:
                  $ref: "#/components/examples/ProviderTimeout"

  /corridors:
    get:
      operationId: listCorridors
      summary: List GI corridor coverage
      description: >
        List corridors that GI-role providers can quote on, filtered by
        GI BIC, source currency, destination country, and instrument type.
        Two valid callers: (1) DA banks call directly at onboarding/catalog
        refresh to discover which GIs serve which corridors; (2) the Swift
        Eligibility API syncs from this endpoint periodically (background,
        not per-payment) and embeds FX capability in its own responses.
        Not an eligibility check. The Swift Eligibility API (DA 4.1 Future)
        aggregates data from all GIs and makes the eligibility determination.
      tags:
        - Corridors
      parameters:
        - $ref: "#/components/parameters/X-BIC"
        - name: source_currency
          in: query
          schema:
            type: string
            maxLength: 3
          example: "USD"
          description: Filter by source currency (ISO 4217)
        - name: destination_currency
          in: query
          schema:
            type: string
            maxLength: 3
          example: "COP"
          description: Filter by destination currency (ISO 4217)
        - name: destination_country
          in: query
          schema:
            type: string
            maxLength: 2
          example: "CO"
          description: Filter by destination country (ISO 3166-1 alpha-2)
        - name: instrument_type
          in: query
          schema:
            type: string
            maxLength: 20
            enum:
              - bank_account
              - mobile_wallet
              - card
              - cash_pickup
          example: "bank_account"
          description: Filter by delivery instrument type
        - name: offset
          in: query
          schema:
            type: integer
            minimum: 0
          example: 0
          description: The starting position of the results window relative to the start of the collection
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
          example: 25
          description: Maximum number of items to return in a page. If unspecified, the default limit will be returned. If greater than the maximum permitted, the API will return the maximum permitted limit.
      responses:
        "200":
          description: Corridors listed
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                type: object
                required:
                  - corridors
                  - pagination
                properties:
                  corridors:
                    type: array
                    maxItems: 100
                    items:
                      $ref: "#/components/schemas/Corridor"
                  pagination:
                    $ref: "#/components/schemas/Pagination"
              examples:
                corridors_found:
                  summary: Two corridors across different geographies
                  description: |
                    GI serves multiple corridors across different markets. Each corridor shows
                    the full capability set: instruments, transaction types, limits, cut-off times,
                    and available settlement models. DA banks use this to build product catalogs.
                  value:
                    corridors:
                      - corridor_id: "USD-COP-CO"
                        source_currency: "USD"
                        destination_currency: "COP"
                        destination_country: "CO"
                        gi_bic: "ALPAGB2LXXX"
                        supported_instruments:
                          - "bank_account"
                          - "mobile_wallet"
                        supported_transaction_types:
                          - "p2p"
                          - "b2b"
                          - "b2p"
                        min_amount: "10.00"
                        max_amount: "50000.00"
                        cut_off_times:
                          - day_of_week: "MON-FRI"
                            cut_off_time: "16:00"
                            timezone: "America/Bogota"
                        settlement_models:
                          - "spot"
                          - "inst"
                        provider_count: 2
                      - corridor_id: "EUR-INR-IN"
                        source_currency: "EUR"
                        destination_currency: "INR"
                        destination_country: "IN"
                        gi_bic: "ALPAGB2LXXX"
                        supported_instruments:
                          - "bank_account"
                        supported_transaction_types:
                          - "p2p"
                          - "b2p"
                        min_amount: "20.00"
                        max_amount: "25000.00"
                        cut_off_times:
                          - day_of_week: "MON-FRI"
                            cut_off_time: "14:00"
                            timezone: "Asia/Kolkata"
                        settlement_models:
                          - "tom"
                          - "spot"
                        provider_count: 1
                    pagination:
                      offset: 0
                      limit: 25
                      total_items: 2
                      total_pages: 1
                      first: "https://api.swiftnet.sipn.swift.com/swift/community-fx/v1/corridors?offset=0&limit=25"
                      last: "https://api.swiftnet.sipn.swift.com/swift/community-fx/v1/corridors?offset=0&limit=25"
                no_corridors:
                  summary: No corridors match the filters
                  description: |
                    The GI does not serve any corridors matching the requested filters.
                    The DA should check filter parameters or try a different GI (different X-BIC).
                  value:
                    corridors: []
                    pagination:
                      offset: 0
                      limit: 25
                      total_items: 0
                      total_pages: 0
                      first: "https://api.swiftnet.sipn.swift.com/swift/community-fx/v1/corridors?offset=0&limit=25"
                      last: "https://api.swiftnet.sipn.swift.com/swift/community-fx/v1/corridors?offset=0&limit=25"
        "400":
          description: Bad Request
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Missing_Required_Field:
                  $ref: "#/components/examples/BadRequest_MissingRequiredField"
        "401":
          description: Unauthorized
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Invalid_Token:
                  $ref: "#/components/examples/InvalidToken"
                Inconsistent_Client:
                  $ref: "#/components/examples/InconsistentClient"
        "403":
          description: Forbidden
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Insufficient_Scope:
                  $ref: "#/components/examples/InsufficientScope"
        "404":
          description: Not Found
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Resource_Not_Found:
                  $ref: "#/components/examples/ResourceNotFound"
        "429":
          description: Too Many Requests
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Rate_Limit_Exceeded:
                  $ref: "#/components/examples/RateLimitExceeded"
        "503":
          description: Service Unavailable
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Unavailable:
                  $ref: "#/components/examples/ProviderUnavailable"
                Provider_Maintenance:
                  $ref: "#/components/examples/ProviderMaintenance"
        "504":
          description: Gateway Timeout
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Timeout:
                  $ref: "#/components/examples/ProviderTimeout"

  /corridors/{corridor_id}:
    get:
      operationId: getCorridor
      summary: Get a specific corridor by ID
      description: >
        Retrieve a single corridor record by its unique corridor_id.
        The X-BIC header routes to the correct GI.
        Useful for DA banks verifying a specific currency pair and instrument
        combination before requesting a quote.
      tags:
        - Corridors
      parameters:
        - $ref: "#/components/parameters/X-BIC"
        - name: corridor_id
          in: path
          required: true
          schema:
            type: string
            maxLength: 50
          example: "USD-COP-CO"
          description: Unique corridor identifier (e.g. source_currency-dest_currency-dest_country)
      responses:
        "200":
          description: Corridor record retrieved
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Corridor"
              examples:
                usd_cop_corridor:
                  summary: USD-COP Colombia corridor
                  description: |
                    A standard USD-to-COP corridor serving Colombia via both bank account
                    and mobile wallet. Supports spot and instant settlement.
                  value:
                    corridor_id: "USD-COP-CO"
                    source_currency: "USD"
                    destination_currency: "COP"
                    destination_country: "CO"
                    gi_bic: "ALPAGB2LXXX"
                    supported_instruments:
                      - "bank_account"
                      - "mobile_wallet"
                    supported_transaction_types:
                      - "p2p"
                      - "b2b"
                      - "b2p"
                    min_amount: "10.00"
                    max_amount: "50000.00"
                    cut_off_times:
                      - day_of_week: "MON-FRI"
                        cut_off_time: "16:00"
                        timezone: "America/Bogota"
                    settlement_models:
                      - "spot"
                      - "inst"
                    provider_count: 2
                eur_inr_corridor:
                  summary: EUR-INR India corridor
                  description: |
                    A EUR-to-INR corridor serving India via bank account only.
                    Supports tom and spot settlement with earlier cut-off times.
                  value:
                    corridor_id: "EUR-INR-IN"
                    source_currency: "EUR"
                    destination_currency: "INR"
                    destination_country: "IN"
                    gi_bic: "ALPAGB2LXXX"
                    supported_instruments:
                      - "bank_account"
                    supported_transaction_types:
                      - "p2p"
                      - "b2p"
                    min_amount: "20.00"
                    max_amount: "25000.00"
                    cut_off_times:
                      - day_of_week: "MON-FRI"
                        cut_off_time: "14:00"
                        timezone: "Asia/Kolkata"
                    settlement_models:
                      - "tom"
                      - "spot"
                    provider_count: 1
        "400":
          description: Bad Request
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Invalid_Corridor_Id:
                  $ref: "#/components/examples/BadRequest_InvalidCorridorId"
        "401":
          description: Unauthorized
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Invalid_Token:
                  $ref: "#/components/examples/InvalidToken"
                Inconsistent_Client:
                  $ref: "#/components/examples/InconsistentClient"
        "403":
          description: Forbidden
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Insufficient_Scope:
                  $ref: "#/components/examples/InsufficientScope"
        "404":
          description: Not Found
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Corridor_Not_Found:
                  $ref: "#/components/examples/CorridorNotFound"
        "429":
          description: Too Many Requests
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Rate_Limit_Exceeded:
                  $ref: "#/components/examples/RateLimitExceeded"
        "503":
          description: Service Unavailable
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Unavailable:
                  $ref: "#/components/examples/ProviderUnavailable"
        "504":
          description: Gateway Timeout
          headers:
            X-Request-ID:
              $ref: "#/components/headers/X-Request-ID"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorMessage"
              examples:
                Provider_Timeout:
                  $ref: "#/components/examples/ProviderTimeout"


components:
  headers:
    X-Request-ID:
      description: End to end tracking ID. This value identifies the callers request in the Swift API Platform.
      required: false
      schema:
        type: string
        maxLength: 75
      example: "cfx-20250115-a1b2c3d4e5f6"

  parameters:
    X-BIC:
      name: X-BIC
      in: header
      required: true
      description: BIC of the target GI backend for request routing.
      schema:
        type: string
        maxLength: 11
        pattern: "^[A-Z0-9]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$"
      example: "ALPAGB2LXXX"

  securitySchemes:
    oauthBearerToken:
      type: http
      scheme: bearer
      bearerFormat: opaque OAuth 2.0
      description: |
        The access token obtained as a result of OAuth 2.0 flows. SWIFT supports the below OAuth grant type for the two environments where the API is exposed.

        * MV-SIPN - jwt-bearer grant type [RFC 7523](https://tools.ietf.org/html/rfc7523) with Signed JWT assertion
        * Internet - jwt-bearer grant type [RFC 7523](https://tools.ietf.org/html/rfc7523) with Signed JWT assertion

        This API uses JWT-Bearer grant type.

        Please visit [SWIFT OAuth Token API](https://developer.swift.com/swift-oauth-token-api) page for more information and examples on how to generate an OAuth token.

        In this declaration only the basic security element to transport the bearer token of an OAuth2 process is declared.

        Required scope: `swift.fxcommunity.api`.

  schemas:
    FxQuoteRequest:
      type: object
      description: >
        FX quote request. Exactly one of source_amount or destination_amount
        must be provided (mutually exclusive; at least one is required).
      required:
        - source_currency
        - destination_currency
        - instrument_type
        - transaction_type
      properties:
        source_currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Source currency (ISO 4217)
        destination_currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Destination currency (ISO 4217)
        source_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Source amount (mutually exclusive with destination_amount; exactly one of source_amount or destination_amount must be provided)
        destination_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Destination amount (mutually exclusive with source_amount; exactly one of source_amount or destination_amount must be provided)
        instrument_type:
          type: string
          maxLength: 20
          enum:
            - bank_account
            - mobile_wallet
            - card
            - cash_pickup
            - all
          description: >-
            Delivery instrument type. Use 'all' to request quotes for every
            valid instrument combination (response will contain specific
            values). The response contains at most 20 quotes (maxItems).
            If the GI has more combinations available, it returns the 20
            with the best fx_rate. To get quotes for a specific instrument,
            set instrument_type to that value instead of 'all'.
        transaction_type:
          type: string
          maxLength: 10
          enum:
            - p2p
            - p2b
            - b2p
            - b2b
            - c2c
            - c2b
            - b2c
            - all
          description: >-
            Transaction type. Use 'all' to request quotes for all supported
            transaction types (response will contain specific values).
        purpose_code:
          type: string
          maxLength: 10
          description: >-
            Purpose of remittance (ISO 20022 ExternalPurpose1Code,
            e.g. SALA for salary, PENS for pension).
        instructing_agent_bic:
          type: string
          maxLength: 11
          pattern: "^[A-Z0-9]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$"
          description: BIC of the requesting institution (ISO 9362)
        idempotency_key:
          type: string
          maxLength: 36
          pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          description: >-
            Idempotency key (UUID v4) for duplicate prevention. If a request
            is retried with the same idempotency_key within the quote TTL
            window, the GI must return the original quote(s) without creating
            duplicates. Clients should always set this field for safe retries.
            If the same idempotency_key is resubmitted with different request
            parameters, the GI must reject with HTTP 400 and error code
            SwAP500.

    FxQuote:
      type: object
      required:
        - quote_id
        - created_at
        - source_currency
        - destination_currency
        - fx_rate
        - source_amount
        - destination_amount
        - expires_at
        - ttl_seconds
        - instrument_type
        - transaction_type
        - settlement_type
        - estimated_delivery
        - conversion_fee
        - charge_type
        - total_debit_amount
        - status
      properties:
        quote_id:
          type: string
          maxLength: 36
          description: >-
            Unique quote identifier. The DA includes this value in the
            pacs.008 to link the payment to the locked FX rate.
        created_at:
          type: string
          format: date-time
          maxLength: 30
          description: Quote creation timestamp (ISO 8601)
        source_currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Source currency (ISO 4217)
        destination_currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Destination currency (ISO 4217)
        fx_rate:
          type: string
          maxLength: 25
          pattern: '^\d{1,10}\.\d{1,10}$'
          description: FX rate as decimal string (10-decimal precision)
        source_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Source amount
        destination_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Destination amount
        expires_at:
          type: string
          format: date-time
          maxLength: 30
          description: Quote expiry timestamp (ISO 8601)
        ttl_seconds:
          type: integer
          minimum: 0
          description: Seconds until quote expiry
        instrument_type:
          type: string
          maxLength: 20
          enum:
            - bank_account
            - mobile_wallet
            - card
            - cash_pickup
          description: Delivery instrument type
        transaction_type:
          type: string
          maxLength: 10
          enum:
            - p2p
            - p2b
            - b2p
            - b2b
            - c2c
            - c2b
            - b2c
          description: Transaction type
        settlement_type:
          type: string
          maxLength: 10
          enum:
            - cash
            - tom
            - spot
            - inst
          description: Settlement model
        estimated_delivery:
          type: string
          format: date-time
          maxLength: 30
          description: Estimated Delivery Date (ISO date)
        estimated_delivery_duration:
          type: string
          maxLength: 10
          description: ISO 8601 duration (e.g. PT2H, P1D)
        value_date:
          type: string
          format: date
          maxLength: 10
          description: Settlement value date (ISO 8601)
        conversion_fee:
          $ref: "#/components/schemas/Fee"
        charge_type:
          type: string
          maxLength: 4
          enum:
            - DEBT
            - SLEV
          description: >-
            Charge bearer (ISO 20022 ChrgBr). This API supports DEBT
            (all charges borne by debtor) and SLEV (charges follow service
            level agreement) only.
        total_debit_amount:
          $ref: "#/components/schemas/MoneyAmount"
        min_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Minimum transaction amount for this combination
        max_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Maximum transaction amount for this combination
        scheme:
          type: string
          maxLength: 20
          description: Payment scheme identifier
        status:
          type: string
          maxLength: 10
          enum:
            - active
            - expired
          description: >-
            Quote lifecycle status. Quotes are created with status 'active'.
            They transition to 'expired' when expires_at is reached
            (server-side, automatic).

    Fee:
      type: object
      description: >
        The FX provider's conversion fee for this quote. This is what the provider
        charges for performing the FX conversion. It does not include Swift fees,
        correspondent agent fees, or other payment infrastructure charges; the DA
        assembles those from separate platform sources.
      required:
        - amount
        - currency
      properties:
        amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Fee amount as decimal string
        currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Fee currency (ISO 4217)

    MoneyAmount:
      type: object
      required:
        - amount
        - currency
      properties:
        amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Monetary amount as decimal string
        currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Currency code (ISO 4217)

    Corridor:
      type: object
      required:
        - corridor_id
        - source_currency
        - destination_currency
        - destination_country
        - supported_instruments
        - supported_transaction_types
        - min_amount
        - max_amount
      properties:
        corridor_id:
          type: string
          maxLength: 50
          pattern: '^[A-Z]{3}-[A-Z]{3}-[A-Z]{2}$'
          description: Unique corridor identifier in format SOURCE_CCY-DEST_CCY-DEST_COUNTRY (e.g. USD-COP-CO)
        source_currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Source currency (ISO 4217)
        destination_currency:
          type: string
          maxLength: 3
          pattern: "^[A-Z]{3}$"
          description: Destination currency (ISO 4217)
        destination_country:
          type: string
          maxLength: 2
          pattern: "^[A-Z]{2}$"
          description: Destination country (ISO 3166-1 alpha-2)
        gi_bic:
          type: string
          maxLength: 11
          pattern: "^[A-Z0-9]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$"
          description: BIC of the GI serving this corridor (ISO 9362)
        supported_instruments:
          type: array
          items:
            type: string
            maxLength: 20
            enum:
              - bank_account
              - mobile_wallet
              - card
              - cash_pickup
          description: Supported instrument types
        supported_transaction_types:
          type: array
          items:
            type: string
            maxLength: 10
            enum:
              - p2p
              - p2b
              - b2p
              - b2b
              - c2c
              - c2b
              - b2c
          description: Supported transaction types
        min_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Minimum transaction amount
        max_amount:
          type: string
          maxLength: 20
          pattern: '^\d{1,18}(\.\d{1,5})?$'
          description: Maximum transaction amount
        cut_off_times:
          type: array
          items:
            type: object
            required:
              - cut_off_time
              - timezone
            properties:
              day_of_week:
                type: string
                maxLength: 10
                description: Day(s) of week (e.g. MON-FRI, SAT)
              cut_off_time:
                type: string
                maxLength: 10
                description: Cut-off time in HH:MM format
              timezone:
                type: string
                maxLength: 30
                description: IANA timezone identifier (e.g. America/Bogota)
          description: Processing cut-off times
        settlement_models:
          type: array
          items:
            type: string
            maxLength: 10
            enum:
              - cash
              - tom
              - spot
              - inst
          description: Available settlement models
        provider_count:
          type: integer
          description: Number of providers serving this corridor

    Pagination:
      type: object
      description: >
        Offset/limit pagination metadata following the Swift API Style Guide.
        Includes link-based navigation (first, next, previous, last) for
        traversing result pages.
      required:
        - offset
        - limit
        - total_items
      properties:
        offset:
          type: integer
          description: The starting position of the current results window
        limit:
          type: integer
          description: Maximum number of items returned in this page
        total_items:
          type: integer
          description: Total number of items matching the query
        total_pages:
          type: integer
          description: Total number of pages (calculated as ceil(total_items / limit))
        first:
          type: string
          format: uri
          maxLength: 2000
          description: Link to the first page of results
        next:
          type: string
          format: uri
          maxLength: 2000
          description: Link to the next page of results (absent on last page)
        previous:
          type: string
          format: uri
          maxLength: 2000
          description: Link to the previous page of results (absent on first page)
        last:
          type: string
          format: uri
          maxLength: 2000
          description: Link to the last page of results

    ErrorMessage:
      description: |
        Custom error schema to support detailed error message.
      type: object
      readOnly: true
      additionalProperties: false
      required:
        - severity
        - code
        - text
      properties:
        severity:
          description: |
            Specifies the severity of the error.
              * Fatal means a failure is permanent and any request should not be retried.
              * Transient means a failure is temporary and any request can be retried after a suitable interval.
          type: string
          enum:
            - Fatal
            - Transient
        code:
          description: Specifies the custom error code as defined by the service provider.
          type: string
          minLength: 3
          maxLength: 30
        text:
          description: Specifies the detail error message identifying the cause of the error.
          type: string
          minLength: 1
          maxLength: 1400
        user_message:
          description: A human-readable text describing the error.
          type: string
          minLength: 1
          maxLength: 255
        more_info:
          description: Specifies a URL to find more information about the error.
          type: string
          format: uri

  examples:
    # --- 400 Bad Request ---
    BadRequest_MutuallyExclusiveAmounts:
      summary: Mutually exclusive amounts
      value:
        severity: Fatal
        code: SwAP500
        text: source_amount and destination_amount are mutually exclusive.
        user_message: Make sure the API request conforms to the OpenAPI specification.
    BadRequest_InvalidParameterFormat:
      summary: Invalid parameter format
      value:
        severity: Fatal
        code: SwAP509
        text: Invalid quote_id format.
        user_message: Make sure the API request conforms to the OpenAPI specification.
    BadRequest_MissingRequiredField:
      summary: Missing required field
      value:
        severity: Fatal
        code: SwAP508
        text: Required field source_currency is missing.
        user_message: Make sure the API request conforms to the OpenAPI specification.
    BadRequest_InvalidCorridorId:
      summary: Invalid corridor ID format
      value:
        severity: Fatal
        code: SwAP509
        text: Invalid corridor_id format.
        user_message: Make sure the API request conforms to the OpenAPI specification.
    BadRequest_MissingAmount:
      summary: Neither source nor destination amount provided
      value:
        severity: Fatal
        code: SwAP510
        text: Exactly one of source_amount or destination_amount must be provided.
        user_message: Make sure the API request conforms to the OpenAPI specification.
    BadRequest_InvalidBIC:
      summary: Invalid X-BIC header
      value:
        severity: Fatal
        code: SwAP522
        text: The x-bic provided is not valid or not reachable.
        user_message: Make sure the x-bic provided is valid.
    # --- 401 Unauthorized ---
    InvalidToken:
      summary: Invalid Token
      value:
        severity: Fatal
        code: SwAP502
        text: Invalid or expired access token.
        user_message: Make sure the access token provided is valid, and the API resource exists.
    InconsistentClient:
      summary: Inconsistent Client
      value:
        severity: Fatal
        code: SwAP501
        text: Client certificate BIC does not match X-BIC header.
        user_message: Make sure the access token provided is valid, and the API resource exists.
    # --- 403 Forbidden ---
    InsufficientScope:
      summary: Insufficient scope
      value:
        severity: Fatal
        code: SwAP503
        text: Insufficient scope for swift.fxcommunity.api.
        user_message: Make sure the correct access token is used for the API call.
    # --- 404 Not Found ---
    QuoteNotFound:
      summary: Quote not found
      value:
        severity: Fatal
        code: SwAP506
        text: Quote q-12345-abcde not found.
        user_message: Make sure the resource URL is correctly defined as in the OpenAPI specification.
    CorridorNotFound:
      summary: Corridor not found
      value:
        severity: Fatal
        code: SwAP506
        text: Corridor USD-XXX-YYY not found for the specified GI.
        user_message: Make sure the resource URL is correctly defined as in the OpenAPI specification.
    ResourceNotFound:
      summary: Resource not found
      value:
        severity: Fatal
        code: SwAP506
        text: Resource does not exist.
        user_message: Make sure the resource URL is correctly defined as in the OpenAPI specification.
    # --- 429 Too Many Requests ---
    RateLimitExceeded:
      summary: Rate limit exceeded
      value:
        severity: Transient
        code: SwAP507
        text: Request cannot be processed at this time. Please try again.
        user_message: Refer to Rate Limit and try again.
    # --- 503 Service Unavailable ---
    ProviderUnavailable:
      summary: FX Provider unavailable
      value:
        severity: Transient
        code: SwAP590
        text: The API response arrived late. FX provider temporarily unavailable.
        user_message: Try again. If the error persists, contact Swift Customer Support.
    ProviderMaintenance:
      summary: FX Provider temporarily unavailable
      value:
        severity: Transient
        code: SwAP599
        text: FX provider undergoing scheduled maintenance.
        user_message: Try again. If the error persists, contact Swift Customer Support.
    # --- 504 Gateway Timeout ---
    ProviderTimeout:
      summary: Gateway Timeout
      value:
        severity: Transient
        code: SwAP591
        text: The API provider cannot be reached.
        user_message: Contact Swift Customer Support.