Orders
An Order is what actually moves money: it spends a
previously created quotation and executes the payout to a
named beneficiary. createOrder creates one, listOrders walks the
company's order history, and getOrder reads a single order by id. See
order status for what the status field
reports through the order's lifecycle.
createOrder(...)β
Spends a quotation and creates an order for the specified beneficiary and payment instructions.
Signatureβ
createOrder(req: CreateOrderRequest, idempotencyKey?: string): Promise<Order>
Parametersβ
| Name | Type | Required | Description |
|---|---|---|---|
req.quotation_id | string | Yes | UUID of the quotation from createQuotation. Single-use. |
req.metadata | Record<string, string> | No | Free-form key/value pairs, echoed back untouched on reads. |
req.purpose | string | Yes | Remittance purpose. One of FAMILY_SUPPORT, PAYMENT_OF_BILLS, PURCHASE_OF_GOODS, PROFESSIONAL_SERVICES, RENTAL_OF_SPACES, INVESTMENTS, COMMISSIONS_LOANS_CAPITAL_INCREASE, TRANSPORTATION_COSTS, FEES. |
req.sender.names | string | Yes | Sender's given name(s). |
req.sender.last_names | string | Yes | Sender's last name(s). |
req.sender.document.type | string | Yes | Document type, e.g. "CC". |
req.sender.document.id | string | Yes | Document number. |
req.sender.document.country | string | Yes | 2-character ISO alpha-2 country the document was issued in. |
req.sender.country | string | Yes | 2-character ISO alpha-2 sender country. |
req.sender.phone | string | No | Sender phone, E.164 format (e.g. "+584121234567"). Validated client-side when present. Round-trips in sender on reads only when you sent it on create. |
req.sender.email | string | No | Sender email. Validated as an email address when present. Round-trips in sender on reads only when you sent it on create. |
req.destination.receiver.names | string | Yes | Beneficiary's given name(s). |
req.destination.receiver.last_names | string | Yes | Beneficiary's last name(s). |
req.destination.receiver.document.type | string | Yes | Beneficiary document type, e.g. "V". |
req.destination.receiver.document.id | string | Yes | Beneficiary document number. |
req.destination.receiver.document.country | string | Yes | 2-character ISO alpha-2 country the document was issued in. |
req.destination.receiver.email | string | No | Beneficiary email. Validated as an email address when present. |
req.destination.receiver.country | string | Yes | 2-character ISO alpha-2 beneficiary country. |
req.destination.payment_instructions.bank_account | object | One of two | { bank_name, number, type }. Mutually exclusive with bank_phone_account. |
req.destination.payment_instructions.bank_account.bank_name | string | β | A closed catalog code from the Venezuela bank catalog, e.g. "BANCO_BANESCO_VE" β never a commercial name. |
req.destination.payment_instructions.bank_account.number | string | β | Account number. |
req.destination.payment_instructions.bank_account.type | "CHECKING" | "SAVINGS" | "CORRIENTE" | "AHORRO" | β | Account type. |
req.destination.payment_instructions.bank_phone_account | object | One of two | { bank_name, phone_number, document_id? }. Mutually exclusive with bank_account. |
req.destination.payment_instructions.bank_phone_account.bank_name | string | β | Same closed catalog as bank_account.bank_name. |
req.destination.payment_instructions.bank_phone_account.phone_number | string | β | E.164 format, e.g. "+584121234567". |
req.destination.payment_instructions.bank_phone_account.document_id | string | No | Falls back to destination.receiver.document.id server-side when omitted. |
idempotencyKey | string | No | Your idempotency reference. Auto-generated as a UUID v4 when omitted. Echoed back as idempotency_key on the returned order. |
payment_instructions takes exactly one of bank_account or
bank_phone_account β never both, never neither.
Returnsβ
Order:
| Field | Type | Meaning |
|---|---|---|
id | string | Order identifier. |
idempotency_key | string (optional) | The idempotency key echoed back. |
type | string | Order type, e.g. "REMITTANCE". |
status | string | See order status. |
quotation_id | string | The quotation this order spent. |
amount | string | Source-currency amount, as a decimal string. |
currency | string | Source currency. |
metadata | Record<string, string> | Echoed back untouched. |
purpose | string | null (optional) | Remittance purpose, when reported. |
sender | object (optional) | Same shape as the request's sender. Omitted in some states. |
destination.receiver | object (optional) | Same shape as the request's receiver. |
destination.payment_instructions | object (optional) | Adds a read-only bank_display_name (the commercial name resolved from the catalog) next to the codes you sent. |
destination.target_amount / destination.target_currency | string (optional) | Payout amount/currency, once the payout has been dispatched. |
execution.source.status / execution.destination.status | string | Per-leg execution status, e.g. "COMPLETED", "PENDING". |
execution.source.reference_id / execution.destination.reference_id | string | null | Per-leg reference id. |
events | array (optional) | Status-change timeline: { id, from_status, to_status, trigger, reason, message, created_at }. |
failure_code / failure_reason | string | null (optional) | Populated only when status === "FAILED". |
created_at / updated_at | string | ISO 8601 timestamps. |
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: "P2P_PHONE_TRANSFER" },
},
quote: { mode: "SEND_EXACT", amount: "10.00" },
});
const order = await client.createOrder(
{
quotation_id: quotation.id,
purpose: "FAMILY_SUPPORT",
metadata: { invoice_id: "INV-2026-00456" },
sender: {
names: "Ana MarΓa",
last_names: "PΓ©rez GΓ³mez",
document: { type: "CC", id: "1020304050", country: "CO" },
country: "CO",
},
destination: {
receiver: {
names: "Carlos AndrΓ©s",
last_names: "RodrΓguez LΓ³pez",
document: { type: "V", id: "12345678", country: "VE" },
country: "VE",
},
payment_instructions: {
bank_phone_account: {
bank_name: "BNC_VE",
phone_number: "+584121234567",
document_id: "12345678",
},
},
},
},
"invoice-2026-00456", // idempotency key β comes back as order.idempotency_key
);
console.log(order.id, order.status, order.idempotency_key);
Errorsβ
Client-side, before any network call (RetornaSdkError):
req.quotation_idis not a valid UUID.req.purposeis missing or outside the closed catalog.- Any required sender/receiver field is empty, a country code is not 2
characters, the receiver
emailis not a valid address,sender.phoneis not E.164, orsender.emailis not a valid address. payment_instructionshas zero or both ofbank_account/bank_phone_accountset.bank_nameis outside the bank catalog, the bank accounttypeis outsideCHECKING/SAVINGS/CORRIENTE/AHORRO, orphone_numberis not E.164.idempotencyKeywas passed explicitly as an empty string.
From the API (RetornaB2BError, see the error catalog):
B2B_UNAUTHORIZEDβ credentials, token, or signature rejected.B2B_QUOTATION_NOT_FOUNDβ the quotation does not exist or is not yours.B2B_QUOTATION_EXPIREDβ the quotation expired before the order was created.B2B_QUOTATION_MISMATCHβ the order does not match the quotation's terms.B2B_QUOTATION_ALREADY_USEDβ the quotation already backs another order.B2B_INSUFFICIENT_BALANCEβ wallet balance is lower than the order requires.B2B_BENEFICIARY_INVALIDβ beneficiary data is invalid for the payout method.B2B_IDEMPOTENCY_CONFLICTβ the sameX-Idempotency-Keywas reused with a different request body.B2B_RATE_LIMITED/B2B_PROVIDER_REJECTED/B2B_PROVIDER_UNAVAILABLE/B2B_UNKNOWNβ see the category-based retry policy.
Notesβ
- Omit
idempotencyKeyand the SDK generates a UUID v4 for you; pass your own reference (an invoice id, a payment run id) and it comes back asorder.idempotency_keyβ see idempotency. - A retry of
createOrderis only safe with the same idempotency key as the original attempt. bank_nameis always a catalog code, never a commercial name β"BANCO_BANESCO_VE", not"Banesco".
API referenceβ
listOrders(params)β
Lists the company's orders, newest activity first, with cursor pagination and optional filters.
Signatureβ
listOrders(params?: ListOrdersParams): Promise<OrdersListResponse>
Parametersβ
| Name | Type | Required | Description |
|---|---|---|---|
params.cursor | string | No | Opaque cursor from a previous page's pagination.next_cursor. Omit for the first page. |
params.limit | number | No | Page size, 1β100, default 20. Fixed for the whole walk once you pass a cursor. |
params.status | string | No | Filter by order status. |
params.type | string | No | Filter by transaction type, e.g. "WALLET_TO_POG". Free-form string, a single value β unlike status, it does not take a comma-separated list. |
params.idempotency_key | string | No | Filter by the idempotency key you sent on create. |
params.created_from | string | No | ISO 8601 date or date-time, inclusive lower bound. |
params.created_to | string | No | ISO 8601 date or date-time, inclusive upper bound. |
Returnsβ
OrdersListResponse:
| Field | Type | Meaning |
|---|---|---|
data | Order[] | See the Order field table under createOrder above. |
pagination.next_cursor | string | null | Opaque next-page token; null once the walk is finished. |
pagination.has_more | boolean | Same end-of-list condition as a null next_cursor. |
pagination.limit | number | Effective page size of the walk. |
pagination.total | number | null | Total of the filtered dataset, or null when unknown. |
Exampleβ
let cursor: string | undefined;
do {
const page = await client.listOrders({ cursor, limit: 50, status: "COMPLETED" });
for (const order of page.data) {
console.log(order.id, order.status, order.amount, order.currency);
}
cursor = page.pagination.next_cursor ?? undefined;
} while (cursor);
Errorsβ
Client-side (RetornaSdkError):
params.limitset but not an integer between 1 and 100.
From the API (RetornaB2BError):
B2B_UNAUTHORIZEDβ credentials, token, or signature rejected.B2B_INVALID_PAGINATION_CURSORβ the cursor could not be decoded, or was not issued by this listing.B2B_RATE_LIMITEDβ too many requests; retry with backoff.
Notesβ
- See pagination for the full cursor rules β they apply identically to order listings and wallet transactions.
- Keep filters identical across every call in a paging loop; changing them mid-walk invalidates the cursor's assumptions.
idempotency_keyis precise enough to make paging moot when you already know the idempotency key you are looking for.
API referenceβ
getOrder(id)β
Reads a single order by id.
Signatureβ
getOrder(id: string): Promise<Order>
Parametersβ
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The order id. Between 1 and 100 characters. |
Returnsβ
Order β same shape as createOrder above.
Exampleβ
const order = await client.getOrder("0190f9b2-3c4d-4e5f-8a6b-7c8d9e0f1a2b");
console.log(order.status, order.execution.destination.status);
Errorsβ
Client-side (RetornaSdkError):
idempty or longer than 100 characters.
From the API (RetornaB2BError):
B2B_UNAUTHORIZEDβ credentials, token, or signature rejected.B2B_ORDER_NOT_FOUNDβ the order does not exist, or does not belong to your company.
Notesβ
- Read-only. Poll it (or better, use
events) to follow an order across status transitions instead of assuming a single terminal call.