Quotes

Create an FX quote

Quotes are opaque and indicative (floating: the rate re-derives at execution), and carry the OZAV all-in client-facing rate. When enabled, they also carry the additional client-selected spread in basis points. A quote is executed by creating a transfer that references it.

Setting your own spread (revenue share). Pass the optional spread_bps to add basis points on top of the OZAV all-in rate for this quote. This value is your additional client-selected spread; it rides the quote through to settlement and is echoed back as exchange_conditions.spread_bps. OZAV cost, floor, margin, and split analytics are internal and are never exposed in the public response. Availability of client-selected spread is gated on enablement for your organization.

Sandbox. With a test key (ozav_sk_test_), quotes are simulated. Sandbox quotes use the current production reference for the currency pair plus a 1 bp sandbox margin and your configured spread, the way production prices them. When no current reference exists for a pair, a fixed table stands in. Sandbox quotes are not executable.

post/quotes

Request

  • Base URL
    https://developers.ozav.io/v2
  • Auth
    • API key in header X-API-Key
    • or HTTP bearer

Request body

customer_idstring required

The opaque customer id (ozav_cus_...). Resolved scoped to the caller; an unknown or cross-tenant id returns 404.

source_rail'pix' | 'fedwire' | 'sepa' | 'spei' | 'swift' | 'faster_payments' | 'uaefts' | 'eft' | 'cnaps' | 'zengin' | 'nip' | 'cce' | 'rtc'

The rails a request can name: every value of Rail except ach and co_transfer, which are not offered and appear only on older records.

destination_rail'pix' | 'fedwire' | 'sepa' | 'spei' | 'swift' | 'faster_payments' | 'uaefts' | 'eft' | 'cnaps' | 'zengin' | 'nip' | 'cce' | 'rtc'

The rails a request can name: every value of Rail except ach and co_transfer, which are not offered and appear only on older records.

destination_countrystring

Optional. ISO 3166-1 alpha-2 country of the beneficiary's bank, for a fiat target. Some currencies cost more to deliver in one country than another (USD paid in China, say), and the quote prices the country you send. Without it, the quote uses the currency's default country. A currency priced only for other countries answers 422 CORRIDOR_NOT_PRICED_FOR_COUNTRY (param: destination_country). It cannot be combined with via yet (400 DESTINATION_COUNTRY_NOT_SUPPORTED_WITH_VIA).

spread_bpsinteger

Optional. Additional client-selected spread for this quote, in integer basis points. This is the spread you charge your end customer, not an OZAV charge; it is revenue-shared with OZAV under your commercial agreement. Available only when enabled for your organization. A non-integer, negative, or out-of-range value is rejected with 400.

It is applied inside rate. The quote you receive is already marked up by this many basis points, so comparing that rate to a market reference (an exchange spot price, say) will look worse by about this amount. It is echoed back as exchange_conditions.spread_bps, and exchange_conditions.rate_without_spread returns the rate before it.

Omitting it applies your configured default, which can be different from 0 if one was negotiated for your organization. Send 0 explicitly to quote at the OZAV all-in rate (all-in except for any amount_deducted).

BRL to BRS has a tighter ceiling than the maximum above. On that corridor the total charged spread cannot exceed 1000 bps, and the OZAV margin for the corridor counts towards that total, so the largest value you can send is lower than 1000 by that margin. Above the ceiling the quote is refused with 422 BRS_SPREAD_ABOVE_CAP (param: spread_bps, details.max_total_spread_bps), never silently trimmed to fit: a quote that froze a value the settlement would refuse would take payment for an operation that cannot complete. The same request on the quote and on the payment intent is refused the same way.

funding_source'incoming_transfer' | 'named_account_balance'

Optional. How the source fiat is funded. incoming_transfer includes the measured inbound cost (USD SWIFT US$ 35; EUR SEPA / GBP Faster Payments US$ 5, deducted from the credit). named_account_balance converts funds already on the named account and includes the outbound cost to the desk (USD wire US$ 35 + 12 bps; EUR/GBP local US$ 5 + 12 bps, charged on top). Omitted behaves as incoming_transfer for USD, EUR and GBP.

facility_previewboolean

Ask for the FX rate lock conditions alongside the quote. When true and your organization has the facility contracted, the response carries an extra facility block; POST /transfers then accepts its terms_version as facility_terms_version. This is the only place that value comes from.

Silent when unavailable. A client without the facility gets a normal 201 quote with no facility block and no error - the preview never fails a quote, because the quote is the product. Read the absence of the block as "not available for this account", and use POST /transfers (which refuses loudly with 422 FACILITY_LOCK_UNAVAILABLE and a details.reason) when you need to know why.

It prices, it does not reserve. capacity_guaranteed is always false: room under the shared ceiling is resolved at acceptance, inside the lock. A preview that promised capacity would be a promise the design cannot honour.

Example request

{
  "source": {
    "amount": "1250.00"
  },
  "target": {
    "amount": "1250.00"
  },
  "destination_country": "CN"
}

Response

The quote.

idstring required

Opaque quote identifier, prefixed ozav_q_.

object'quote' required

Resource type discriminator; always the literal quote.

customer_idstring

Opaque customer id (prefixed ozav_cus_) the quote was created for.

rate_type'floating' | 'locked' required

How the rate behaves until execution.

  • floating - indicative; the rate re-derives at execution time. Every quote returns this today, and it comes with expires_at: null: a firm price holds for only a few seconds, so OZAV re-quotes at execution instead of expiring your quote. Treat rate as indicative: what executes can differ from the quote.
  • locked - held fixed until expires_at. Not served on this API yet. When it ships it will require the price-lock facility enabled on your account, and will carry a real expires_at. Ask OZAV if you need a firm price today.

Do not branch on expires_at being non-null: on floating it is always null, in sandbox and in production alike.

ratestring required

The FX rate as a decimal string - target-currency units per one source unit, all-in except for any amount_deducted (it already carries any spread_bps you added). Indicative on a floating quote, which is every quote today: it re-derives at execution. On the quote, source.amount x rate gives target.amount (with amount_deducted present, (source.amount - amount_deducted) x rate).

expires_atstring date-time nullable required

When the quote expires (RFC 3339 / ISO 8601, UTC).

null on a floating quote is the normal answer, not a missing value, and it does not mean the quote is valid forever. A floating rate is indicative: it re-derives at execution, so there is no window to "accept" it within. Quote as close to execution as you can, and read the rate you are given at execution as the one that applies.

A timestamp appears only when the rate is held: a locked quote, which expires at this instant and is refused after it.

created_atstring date-time required

When the quote was created (RFC 3339 / ISO 8601, UTC).

Example response

{
  "source": {
    "amount": "1250.00"
  },
  "target": {
    "amount": "1250.00"
  },
  "legs": [
    {
      "source": {
        "amount": "1250.00"
      },
      "target": {
        "amount": "1250.00"
      }
    }
  ]
}

Changes

No recorded changes to this operation across all 1 revision of this API.