Saltar al contenido principal

Cotizaciones

Una Quote fija la tasa de cambio y las comisiones de una transferencia antes de que te comprometas a ella. QuotationsClient envuelve los dos endpoints que crean y leen cotizaciones. Cada orden referencia exactamente una cotización, y una cotización respalda exactamente una orden, para siempre — consulta el resumen del SDK para el recorrido completo de cotización a orden.

Accede a estos métodos directamente en RetornaClient (client.createQuotation(...)) o a través del sub-cliente (client.quotations().createQuotation(...)) — las dos formas ejecutan el mismo código.

createQuotation(request)​

Cotiza una transferencia para un corredor y un método de pago dados, devolviendo una tasa sobre la que puedes actuar antes de que expire.

Firma​

public QuotationDetail createQuotation(CreateQuotationRequest request)

Parámetros​

NombreTipoRequeridoDescripción
requestCreateQuotationRequestSíEl pedido de cotización. Ver los componentes abajo.

Componentes de CreateQuotationRequest:

ComponenteTipoRequeridoDescripción
sourceQuotationSourceSíLado de fondeo. Lleva una única currency (String) — la moneda desde la que fondeas.
destinationQuotationDestinationSícountry (String, ISO 3166-1 alpha-2 de 2 caracteres, en mayúsculas), currency (String, moneda de destino), payoutMethod (QuotationPayoutMethod, requerido).
destination.payoutMethod.typePayoutMethodTypeSíUno de los tipos de método de pago soportados por la plataforma. Anidado un nivel dentro de destination.payoutMethod.
quoteQuotationQuoteSímode (QuoteMode: SEND_EXACT fija el monto de origen, RECEIVE_EXACT fija el monto de destino) y amount (String, decimal con hasta 6 decimales, según ^\d+(\.\d{1,6})?$).

Retorno​

QuotationDetail:

AccesorTipoSignificado
id()StringId de la cotización. Pásalo en CreateOrderRequest.quotationId para usarla.
source()QuotationSourceDetailLado de origen: currency(), decimals() (int), grossAmount() (String, antes de comisiones), netAmount() (String, después de comisiones).
destination()QuotationDestinationDetailEl corredor que fijó la cotización: country() (String, ISO-2) y payoutMethod().type() (PayoutMethodType). Las instrucciones de pago de la orden tienen que coincidir con el tipo de payout, o createOrder falla con B2B_QUOTATION_MISMATCH. Los dos son null solo cuando la red no pudo asociar una tasa — no crees una orden sobre esa cotización.
target()QuotationTargetDetailLado de destino: currency(), decimals() (int), amount() (String, lo que recibe el beneficiario).
exchangeRate()ExchangeRatevalue() (String), quotedAt() (OffsetDateTime), expiresAt() (OffsetDateTime). Revisa expiresAt() antes de usar la cotización.
fees()QuotationFeestotalInSourceCurrency() (String) y breakdown() (List<FeeBreakdownItem>). Cada item tiene description(), pricingType() (PERCENTAGE o FIXED), appliedTo() (etapa a la que se aplica la comisión), value(), y currency().

El JSON en el wire es snake_case (gross_amount, exchange_rate, total_in_source_currency, ...); los accesores de Java de arriba son camelCase — Jackson mapea entre las dos formas por ti.

Ejemplo​

import app.retorna.sdk.RetornaClient;
import app.retorna.sdk.RetornaClientBuilder;
import app.retorna.sdk.core.environment.RetornaEnvironment;
import app.retorna.sdk.models.quotation.CreateQuotationRequest;
import app.retorna.sdk.models.quotation.PayoutMethodType;
import app.retorna.sdk.models.quotation.QuotationDestination;
import app.retorna.sdk.models.quotation.QuotationDetail;
import app.retorna.sdk.models.quotation.QuotationPayoutMethod;
import app.retorna.sdk.models.quotation.QuotationQuote;
import app.retorna.sdk.models.quotation.QuotationSource;
import app.retorna.sdk.models.quotation.QuoteMode;

RetornaClient client = new RetornaClientBuilder()
.environment(RetornaEnvironment.SANDBOX)
.clientId(System.getenv("RETORNA_CLIENT_ID"))
.clientSecret(System.getenv("RETORNA_CLIENT_SECRET"))
.privateKey(System.getenv("RETORNA_PRIVATE_KEY"))
.buildClient();

QuotationDetail quote = client.createQuotation(new CreateQuotationRequest(
new QuotationSource("USDR"),
new QuotationDestination("VE", "VES",
new QuotationPayoutMethod(PayoutMethodType.BANK_TRANSFER)),
new QuotationQuote(QuoteMode.SEND_EXACT, "10.00")));

System.out.printf("id=%s rate=%s expiresAt=%s%n",
quote.id(), quote.exchangeRate().value(), quote.exchangeRate().expiresAt());
System.out.printf("payout=%s → construye la orden con las instrucciones que coincidan%n",
quote.destination().payoutMethod().type()); // P2P_PHONE_TRANSFER → BankPhoneAccount
System.out.printf("receiver gets %s %s (fees: %s %s)%n",
quote.target().amount(), quote.target().currency(),
quote.fees().totalInSourceCurrency(), quote.source().currency());

Errores​

  • IllegalArgumentException — se lanza de forma sincrónica, antes de que salga cualquier request, cuando falta o está mal formado un campo requerido (source.currency vacío, un destination.country que no son 2 letras mayúsculas, un quote.mode faltante, o un quote.amount que no cumple el patrón decimal).
  • RetornaB2BException con codeEnum() uno de: B2B_RATE_NOT_FOUND — no hay tasa activa para el corredor pedido; B2B_UNAUTHORIZED — token o firma rechazados; B2B_RATE_LIMITED — reintentable, con backoff; B2B_PROVIDER_REJECTED o B2B_PROVIDER_UNAVAILABLE — este último reintentable; B2B_UNKNOWN — reintenta como mucho una vez. Llama a e.codeEnum().isRetryable() en lugar de fijar a mano qué códigos reintentar.
  • RetornaAuthException — falló el propio intercambio de token OAuth2.
  • RetornaSdkException — falla de red o una respuesta que no se pudo deserializar.

Notas​

  • Una cotización es de un solo uso y con vencimiento: revisa exchangeRate().expiresAt() antes de crear la orden, y vuelve a cotizar si ya pasó.
  • quote.amount tiene que ser un string decimal. Pasar un double o perder precisión al construirlo es la forma más común de terminar con un 422 confuso.

Referencia de API​

POST /quotations

getQuotation(id)​

Lee una cotización creada previamente por su id — útil para revisar de nuevo su vencimiento o sus términos antes de usarla.

Firma​

public QuotationDetail getQuotation(String id)

Parámetros​

NombreTipoRequeridoDescripción
idStringSíEl id de la cotización de una llamada previa a createQuotation(). Se valida solo por longitud (1 a 100 caracteres) — trátalo como un string opaco, no como un UUID.

Retorno​

La misma forma de QuotationDetail devuelta por createQuotation arriba.

Ejemplo​

import app.retorna.sdk.RetornaClient;
import app.retorna.sdk.RetornaClientBuilder;
import app.retorna.sdk.core.environment.RetornaEnvironment;
import app.retorna.sdk.models.quotation.QuotationDetail;

RetornaClient client = new RetornaClientBuilder()
.environment(RetornaEnvironment.SANDBOX)
.clientId(System.getenv("RETORNA_CLIENT_ID"))
.clientSecret(System.getenv("RETORNA_CLIENT_SECRET"))
.privateKey(System.getenv("RETORNA_PRIVATE_KEY"))
.buildClient();

QuotationDetail quote = client.getQuotation("0190f9b2-0000-7000-8000-000000000000");
System.out.printf("rate=%s expiresAt=%s%n",
quote.exchangeRate().value(), quote.exchangeRate().expiresAt());

Errores​

  • IllegalArgumentException — id es null, vacío, o más largo que 100 caracteres.
  • RetornaB2BException con codeEnum() uno de: B2B_QUOTATION_NOT_FOUND — no existe o no te pertenece; B2B_UNAUTHORIZED; B2B_RATE_LIMITED — reintentable; B2B_UNKNOWN. Revisa e.codeEnum().isRetryable() antes de reintentar.
  • RetornaAuthException — falla del intercambio de token.
  • RetornaSdkException — falla de red o falla de deserialización.

Notas​

  • El id es opaco. No asumas que es un UUID aunque los ejemplos parezcan uno — el backend no promete ninguna forma más allá de "entre 1 y 100 caracteres."

Referencia de API​

GET /quotations/:id