Cotizaciones
Una cotización fija un tipo de cambio, las comisiones y los
montos resultantes por una ventana corta. Créala antes de crear una orden, y después
referencia su id — una orden que referencia una cotización vencida o ya usada falla
antes de que se mueva el dinero. Consulta Órdenes para create_order.
create_quotation
Fija un tipo de cambio para un corredor de transferencia: una moneda de origen, un país/moneda/método de pago de destino, y el monto que quieres cotizar.
Firma
def create_quotation(self, request: CreateQuotationRequest) -> QuotationDetail:
Parámetros
| Nombre | Tipo | Requerido | Descripción |
|---|---|---|---|
request | CreateQuotationRequest | Sí | La cotización a crear. |
Campos de CreateQuotationRequest:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
source | QuotationSource | Sí | De dónde viene el dinero. Lleva solo currency — agregar algo más da un 400. |
source.currency | str | Sí | Código de moneda no vacío, p. ej. "USDR". |
destination | QuotationDestination | Sí | Adónde va el dinero. |
destination.country | str | Sí | Código de país ISO alpha-2 de 2 caracteres, en mayúsculas, p. ej. "VE". |
destination.currency | str | Sí | Código de moneda no vacío, p. ej. "VES". |
destination.payout_method | QuotationPayoutMethod | Sí | Cómo se le paga al destinatario. |
destination.payout_method.type | PayoutMethodType | Sí | PayoutMethodType.BANK_TRANSFER o PayoutMethodType.P2P_PHONE_TRANSFER. |
quote | QuotationQuote | Sí | El monto que se está cotizando. |
quote.mode | QuoteMode | Sí | QuoteMode.SEND_EXACT (quien envía se desprende de exactamente quote.amount) o QuoteMode.RECEIVE_EXACT (el destinatario recibe exactamente quote.amount). |
quote.amount | str | Sí | String decimal con hasta 6 decimales, p. ej. "56.00". Nunca un float. |
Retorno
QuotationDetail:
| Campo | Tipo | Descripción |
|---|---|---|
id | Optional[str] | El id de la cotización. Pásalo como quotation_id a create_order. |
source | Optional[QuotationSourceDetail] | currency, decimals, gross_amount, net_amount — el lado origen, antes y después de comisiones. |
destination | Optional[QuotationDestinationDetail] | country (ISO-2) y payout_method.type — el corredor que fijó la cotización. Las instrucciones de pago de la orden tienen que coincidir con payout_method.type, o create_order falla con B2B_QUOTATION_MISMATCH. Los dos son None solo cuando la red no pudo asociar una tasa — no crees una orden sobre esa cotización. |
target | Optional[QuotationTargetDetail] | currency, decimals, amount — a qué monto llega el lado destinatario. |
exchange_rate | Optional[ExchangeRate] | value (string decimal), quoted_at, expires_at — el tipo de cambio fijado y su ventana de validez. |
fees | Optional[QuotationFees] | total_in_source_currency más una lista breakdown de FeeBreakdownItem (description, pricing_type, applied_to, value, currency). |
Ejemplo
from retorna_sdk import (
CreateQuotationRequest, QuotationSource, QuotationDestination,
QuotationPayoutMethod, QuotationQuote, QuoteMode, PayoutMethodType,
)
# client is the RetornaClient from the overview's RetornaClient.create(...)
quotation = client.create_quotation(CreateQuotationRequest(
source=QuotationSource(currency="USDR"),
destination=QuotationDestination(
country="VE", currency="VES",
payout_method=QuotationPayoutMethod(type=PayoutMethodType.BANK_TRANSFER)),
quote=QuotationQuote(mode=QuoteMode.SEND_EXACT, amount="56.00"),
))
print(quotation.id, quotation.exchange_rate.value, quotation.target.amount)
print(quotation.destination.payout_method.type) # "P2P_PHONE_TRANSFER" → usa bank_phone_account en la orden
Errores
B2B_RATE_NOT_FOUND— no hay un tipo de cambio activo para este corredor origen/destino/método de pago. Revisaget_routesprimero.B2B_RATE_LIMITED— demasiados requests; reintenta con backoff.B2B_UNAUTHORIZED— token o firma de request inválidos.ValueError— se lanza localmente, antes de mandar cualquier request, cuandorequest,source,destinationoquoteesNone; cuandoquote.modeodestination.payout_method.typeno es un miembro válido del enum; o cuandosource.currency/destination.currencyestá vacío,destination.countryno es un código de 2 letras en mayúsculas, oquote.amountno es un string decimal.
Notas
sourcelleva solocurrency— nada decountryninetwork. El DTO lo exige incluso donde documentación vieja diga lo contrario.- La cotización vence rápido; no la guardes en caché para usarla en requests que puedan tardar más de unos minutos.
Referencia de API
get_quotation
Vuelve a traer una cotización ya creada por su id — útil para verificar si sigue
dentro de su ventana de validez antes de crear una orden a partir de ella.
Firma
def get_quotation(self, quotation_id: str) -> QuotationDetail:
Parámetros
| Nombre | Tipo | Requerido | Descripción |
|---|---|---|---|
quotation_id | str | Sí | Id opaco, de 1 a 100 caracteres — no necesariamente un UUID. |
Retorno
El mismo QuotationDetail que create_quotation — consulta la tabla
de arriba.
Ejemplo
quotation = client.get_quotation(quotation.id)
print(quotation.id, quotation.exchange_rate.expires_at)
Errores
B2B_QUOTATION_NOT_FOUND— el id no existe, o no pertenece a tu compañía.B2B_UNAUTHORIZED— token o firma de request inválidos.ValueError— se lanza localmente cuandoquotation_idesNoneo su longitud está fuera de 1..100 caracteres.
Notas
- Traer una cotización no la extiende ni la refresca —
expires_atqueda fijo desde el momento en que se creó.