Skip to main content

Quotations

A Quote locks in an exchange rate, fees, and the resulting amounts before money moves. createQuotation requests one; getQuotation re-reads it. A quotation is single-use β€” it backs exactly one order, forever β€” and it expires, so the window between quoting and sending matters.

createQuotation(...)​

Requests a new quotation for a source-to-destination corridor and locks in its exchange rate and fees.

Signature​

createQuotation(req: CreateQuotationRequest): Promise<QuotationDetail>

Parameters​

NameTypeRequiredDescription
req.source.currencystringYesAlways "USDR" β€” B2B funds originate from the USDR wallet. Any other value is rejected client-side.
req.destination.countrystringYes2-character ISO alpha-2 destination country code.
req.destination.currencystringYesDestination currency code.
req.destination.payout_method.type"BANK_TRANSFER" | "P2P_PHONE_TRANSFER"YesThe payout method the destination amount will be settled with.
req.quote.mode"SEND_EXACT" | "RECEIVE_EXACT"YesSEND_EXACT fixes the source amount; RECEIVE_EXACT fixes the target amount.
req.quote.amountstringYesDecimal string, up to 6 fractional digits (^\d+(\.\d{1,6})?$).

Returns​

QuotationDetail:

FieldTypeMeaning
idstringQuotation identifier. Pass it as quotation_id to createOrder.
source.currencystringSource currency β€” always "USDR".
source.decimalsnumberDecimal precision of the source amounts.
source.gross_amountstringSource amount before fees.
source.net_amountstringSource amount after fees.
destination.countrystring | nullDestination country the quotation locked (ISO-2).
destination.payout_method.typestring | nullPayout method the quotation locked. The order's payment_instructions must match it, or createOrder fails with B2B_QUOTATION_MISMATCH. Both destination fields are null only when the network could not attach a rate β€” do not build an order on that quotation.
target.currencystringDestination currency.
target.decimalsnumberDecimal precision of the target amount.
target.amountstringAmount the beneficiary receives.
exchange_rate.valuestringThe locked rate, as a decimal string.
exchange_rate.quoted_atstringISO 8601 timestamp the rate was quoted at.
exchange_rate.expires_atstringISO 8601 timestamp the quotation stops being usable.
fees.total_in_source_currencystringTotal fees, expressed in the source currency.
fees.breakdown[].descriptionstringHuman-readable line item.
fees.breakdown[].pricing_type"FEE" | "DISCOUNT"Whether the line adds to or reduces the cost.
fees.breakdown[].applied_tostringBase the line was computed against, e.g. "GROSS" or "NET".
fees.breakdown[].valuestringLine amount, as a decimal string.
fees.breakdown[].currencystringCurrency of the line amount.

Example​

import {
RetornaClientBuilder,
RetornaEnvironment,
} from "@retorna-tech/retorna-gateway-sdk";

const client = new RetornaClientBuilder()
.environment(RetornaEnvironment.SANDBOX)
.clientId(process.env.RETORNA_CLIENT_ID!)
.clientSecret(process.env.RETORNA_CLIENT_SECRET!)
.privateKey(process.env.RETORNA_PRIVATE_KEY!)
.buildClient();

const quotation = await client.createQuotation({
source: { currency: "USDR" },
destination: {
country: "VE",
currency: "VES",
payout_method: { type: "BANK_TRANSFER" },
},
quote: { mode: "SEND_EXACT", amount: "10.00" },
});

console.log(quotation.id, quotation.target.amount, quotation.exchange_rate.expires_at);
console.log(quotation.destination.payout_method.type); // "P2P_PHONE_TRANSFER" β†’ use bank_phone_account on the order

Errors​

Client-side, before any network call (RetornaSdkError):

  • Empty source.currency, destination.currency, or a destination.country that is not exactly 2 characters.
  • destination.payout_method.type outside BANK_TRANSFER / P2P_PHONE_TRANSFER.
  • quote.mode other than SEND_EXACT / RECEIVE_EXACT, or quote.amount not matching the decimal-string format.

From the API (RetornaB2BError, see the error catalog):

  • B2B_UNAUTHORIZED β€” credentials, token, or signature rejected.
  • B2B_RATE_NOT_FOUND β€” no active rate for the requested corridor.
  • B2B_RATE_LIMITED β€” too many requests; retry with backoff.
  • B2B_PROVIDER_UNAVAILABLE β€” the payment network is unreachable; retry with backoff.
  • B2B_UNKNOWN β€” unclassified failure; retry once, then escalate with correlationId.

Notes​

  • source.currency only ever accepts "USDR" β€” funds always originate from the USDR wallet, only the destination corridor varies.
  • The quotation is only good until exchange_rate.expires_at. A createOrder call against an expired quotation fails with B2B_QUOTATION_EXPIRED (see orders) β€” request a fresh quotation instead of retrying.
  • A quotation is single-use: once an order references it, a second createOrder with the same quotation_id fails with B2B_QUOTATION_ALREADY_USED. See idempotency.

API reference​

POST /quotations

getQuotation(id)​

Reads back a previously created quotation by id.

Signature​

getQuotation(id: string): Promise<QuotationDetail>

Parameters​

NameTypeRequiredDescription
idstringYesThe quotation id returned by createQuotation. Between 1 and 100 characters.

Returns​

QuotationDetail β€” same shape as createQuotation above.

Example​

const quotation = await client.getQuotation("a1b2c3d4-e5f6-7890-abcd-ef1234567890");
console.log(quotation.exchange_rate.expires_at);

Errors​

Client-side (RetornaSdkError):

  • id empty or longer than 100 characters.

From the API (RetornaB2BError):

  • B2B_UNAUTHORIZED β€” credentials, token, or signature rejected.
  • B2B_QUOTATION_NOT_FOUND β€” the quotation does not exist, or does not belong to your company.

Notes​

  • Read-only: it does not refresh the rate or extend expires_at.
  • Useful to re-check exchange_rate.expires_at right before calling createOrder, since a quotation you fetched earlier may have expired since.

API reference​

GET /quotations/{id}