> ## Documentation Index
> Fetch the complete documentation index at: https://developers.staging01.melio.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Quote a currency conversion

> Prices a conversion for a payment to an `international-fx` account denominated in a currency other than USD, and returns a short-lived `quoteToken` that locks the rate.

Pass the token as `fxQuoteToken` on `POST /payments` to be charged exactly what was quoted. The token is optional — omit it and the payment is priced again at creation time, at whatever rate then applies.

Fees are priced separately by `POST /tools/fee-calculator`; the two are independent and can be called in either order.




## OpenAPI

````yaml /openapi.json post /tools/fx-quote
openapi: 3.0.3
info:
  title: Melio Payouts API
  version: '1.0'
  description: >
    Self-serve payouts API. Partners onboard an Entity, which is the business

    (organization plus owner, with the details required to be payment-eligible),

    then attach accounts (internal accounts and external accounts) and make

    payments.


    ## Resource ids


    Every resource has an opaque, prefixed id that is stable for the life of the
    resource:

    `ent_` (entity), `pay_` (payment), `acct_` (account, internal or external).

    Ids are Melio-issued; treat them as opaque strings and never parse or
    construct them. To

    attach your own identifier to a resource, use `externalId`.


    ## Pagination


    List endpoints are cursor-paginated and always return results newest-first

    (`createdAt` descending). The response envelope is:


    ```json

    { "data": [ /* resources */ ], "hasMore": true }

    ```


    Page through results with `limit` (1 to 50, default 50) plus a cursor:


    - `startingAfter=<id>`: return the page immediately **after** the given
    resource id
      (the next, older page). This is how you walk forward through a list.
    - `endingBefore=<id>`: return the page immediately **before** the given
    resource id
      (the previous, newer page).

    `startingAfter` and `endingBefore` are mutually exclusive. The cursor is a
    resource id

    you already received (e.g. the `id` of the last item on the current page),
    not an index.

    Keep requesting the next page until `hasMore` is `false`.


    ## Filtering & sorting


    Ordering is fixed (newest-first); there is no `sortBy`. To narrow a list,
    filter it.

    Each list endpoint documents its own filter parameters (there is no generic
    query

    language). Date-range filters use bracket suffixes and accept RFC 3339
    timestamps:

    `created[gte]`, `created[lte]`. Filter by your own identifier with
    `externalId`, and

    by metadata with `metadata[<key>]=<value>` (matches resources whose metadata
    contains

    every supplied key/value pair). Filters combine with AND and compose with
    pagination.


    ## External ids


    Every created resource accepts an optional `externalId`, your own unique
    identifier for

    the resource (≤255 chars, letters/digits/`-`/`_`). It is unique per partner
    per resource

    type: reusing one returns `409 DUPLICATE_EXTERNAL_ID`. Use it to correlate
    Melio resources

    with records in your system and to look resources up (`?externalId=`)
    without storing

    Melio ids. `externalId` identifies a *resource*; it is not a
    request-deduplication key

    (that is the `Idempotency-Key` header, below); the two are complementary.


    ## Idempotency


    Send an `Idempotency-Key` header on every create so retries are safe: the
    original response

    is replayed instead of creating a second resource. It is required on `POST
    /payments`.


    ## Metadata


    Most resources accept a `metadata` object: free-form string key/value pairs
    that Melio

    stores and returns verbatim but never interprets. Limits: up to 50 keys, key
    ≤40 chars,

    value ≤100 chars. Use it to stash your own structured context on a resource;
    it is also

    filterable (see above).


    ## Melio Sonar Session Token


    Write endpoints optionally accept a `Melio-Sonar-Token` header: a signed
    session token

    minted by the MelioSonar SDK on the end user's device, carrying device
    signals used for

    risk evaluation. Omit it when no SDK session is available.
  contact:
    name: Melio Platform External API
    email: platform@melio.com
servers:
  - description: Production
    url: https://api.melio.com/v2
  - description: Staging01
    url: https://api.staging01.melio.com/v2
security: []
tags:
  - name: Entities
    description: >-
      A business you onboard and operate on behalf of: its profile, compliance
      details, and per-operation limitations.
  - name: Accounts
    description: Accounts the entity pays from (internal) and payees it pays to (external).
  - name: Attachments
    description: Supporting documents an entity uploads once and references from a payment.
  - name: Payments
    description: >-
      Money moved from an internal account to an external account, and their
      lifecycle.
  - name: Tools
    description: >-
      Pre-flight calculators for fees, fast-payment eligibility, and delivery
      estimates. No resource is created.
  - name: Webhooks
    description: >-
      Your single endpoint for event notifications, and the events you can
      subscribe to.
paths:
  /tools/fx-quote:
    parameters:
      - $ref: '#/components/parameters/MelioEntityId'
    post:
      tags:
        - Tools
      summary: Quote a currency conversion
      description: >
        Prices a conversion for a payment to an `international-fx` account
        denominated in a currency other than USD, and returns a short-lived
        `quoteToken` that locks the rate.


        Pass the token as `fxQuoteToken` on `POST /payments` to be charged
        exactly what was quoted. The token is optional — omit it and the payment
        is priced again at creation time, at whatever rate then applies.


        Fees are priced separately by `POST /tools/fee-calculator`; the two are
        independent and can be called in either order.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FxQuoteRequest'
            example:
              receivingAccountId: acct_2a4f9c31-77ad-4c1e-8b52-6d3f0a91c4e7
              amount: 100000
              currency: EUR
              purpose: payment for consulting services
      responses:
        '200':
          description: The priced conversion and the token that locks it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FxQuote'
              example:
                currency: EUR
                foreignAmount: 100000
                amount: 110250
                usdToForeignRate: 0.907
                midMarketRate: 0.9125
                quoteToken: >-
                  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb3JlaWduQ3VycmVuY3kiOiJFVVIifQ.sig
                expiresAt: '2026-09-06T12:34:56Z'
        '400':
          description: >
            Validation error (the account does not convert currency, or
            `currency` does not match it), or the currency is not supported
            (UNSUPPORTED_CURRENCY)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Entity or account not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - ApiKey: []
components:
  parameters:
    MelioEntityId:
      name: Melio-Entity-Id
      in: header
      required: true
      description: >-
        Entity the request operates on — an entity id (`ent_<uuid>`) or `me`
        (the partner's sole entity).
      schema:
        type: string
  schemas:
    FxQuoteRequest:
      type: object
      description: >
        Only accounts that actually convert currency can be quoted: an
        `international-fx` account denominated in something other than USD.
        Anything else — a domestic account, a USD-denominated international
        account, or `international-gusd`, which is dollar-denominated — is
        rejected with `400`.
      required:
        - receivingAccountId
        - amount
      properties:
        receivingAccountId:
          type: string
          description: External receiving account id (acct_<id>), the credit account
        amount:
          type: integer
          description: >
            Minor units of `currency` — the amount the counterparty would
            receive.
        currency:
          type: string
          description: >
            Must match the receiving account's currency. Optional, but sending
            it turns a wrong assumption into a `400` instead of a quote in an
            unexpected currency.
          pattern: ^[A-Za-z]{3}$
        purpose:
          type: string
          description: >
            Why the money is being sent. Passed to the currency provider when
            the quote is minted, so send the same value you will send as
            `compliance.purpose` on the payment.
    FxQuote:
      type: object
      description: >
        A priced currency conversion. `foreignAmount` is what the counterparty
        receives and `amount` is what the entity is debited, both in minor units
        of their own currency and both excluding fees.
      required:
        - currency
        - foreignAmount
        - amount
        - usdToForeignRate
        - quoteToken
      properties:
        currency:
          type: string
          description: ISO 4217 code of the currency delivered
        foreignAmount:
          type: integer
          description: Minor units of `currency` delivered to the counterparty
        amount:
          type: integer
          description: Minor units of USD debited from the entity, before fees
        usdToForeignRate:
          type: number
          description: 'The applied rate: units of `currency` per USD'
        midMarketRate:
          type: number
          description: The mid-market reference rate, for comparison
        quoteToken:
          type: string
          description: >
            Opaque, short-lived token locking this rate. Pass it as
            `fxQuoteToken` on `POST /payments`, for a payment of this `amount`
            in this `currency` — the token is checked against both, so it cannot
            be spent on a payment it was not quoted for. Treat it as opaque; its
            format is not part of this contract.
        expiresAt:
          type: string
          format: date-time
          description: When the token stops being accepted. After this, quote again.
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/Error'
    Error:
      type: object
      required:
        - type
        - code
        - message
      properties:
        type:
          type: string
          description: >-
            Coarse, machine-readable error category. Branch on this to handle a
            whole class of failures without enumerating every `code`.
          enum:
            - invalid_request_error
            - authentication_error
            - authorization_error
            - not_found_error
            - conflict_error
            - rate_limit_error
            - service_unavailable_error
            - internal_error
        code:
          type: string
          description: Machine-readable error code.
          enum:
            - VALIDATION_ERROR
            - INVALID_ACCOUNT_TYPE
            - ACCOUNT_NOT_VERIFIED
            - INVALID_DELIVERY_PREFERENCE
            - MCC_REQUIRED
            - MERCHANT_ADDRESS_REQUIRED
            - GOODS_RECEIVED_REQUIRED
            - IDEMPOTENCY_KEY_REQUIRED
            - FEE_CALCULATION_FAILED
            - UNSUPPORTED_CURRENCY
            - FX_QUOTE_INVALID
            - ATTACHMENT_REQUIRED
            - COMPLIANCE_UPLOAD_FAILED
            - ATTACHMENT_UPLOAD_FAILED
            - INTERNATIONAL_NOT_ENABLED
            - ENTITY_ONBOARDING_INCOMPLETE
            - UNAUTHORIZED
            - NOT_FOUND
            - NO_ACTIVE_API_KEY
            - DUPLICATE_ENTITY
            - DUPLICATE_ACCOUNT
            - DUPLICATE_PAYMENT
            - DUPLICATE_EXTERNAL_ID
            - ACCOUNT_IN_USE
            - BUSINESS_NOT_ELIGIBLE
            - PAYMENT_NOT_EDITABLE
            - PAYMENT_NOT_CANCELABLE
            - IDEMPOTENCY_KEY_REUSED
            - IDEMPOTENCY_KEY_IN_PROGRESS
            - IDEMPOTENCY_STORE_UNAVAILABLE
            - INTERNAL_ERROR
        message:
          type: string
          description: Human-readable error message.
        details:
          type: object
          description: Additional error context (e.g. field-level validation failures).
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: api-key

````