Precios en dólares, cobro en bolívares

Fija tus precios en dólares o euros y cobra en bolívares a la tasa BCV del momento del pago.

Para un negocio que piensa sus precios en dólares, como casi todo en Venezuela, pero cobra por Pago Móvil o Débito Inmediato, que mueven bolívares. El ejemplo es un producto de USD 10,00 más IVA.

El modelo

En tu negocioEn Billete
El preciocurrency: "USD" y amount: 1000 en el producto o el plan
Lo que paga tu clienteBolívares a la tasa BCV del momento de pagar
Lo que te quedaBolívares: lo cobrado menos las comisiones (settlement)
El IVATu alícuota, si eres contribuyente, y el taxBehavior de cada precio
  • El precio no cambia con la tasa. El producto vale USD 10,00 hoy y dentro de un mes; lo que cambia es cuántos bolívares son. Así no actualizas precios cada vez que el BCV publica.
  • La conversión la hace Billete al cobrar, nunca tu aplicación: el monto en bolívares sale de la tasa vigente al pagar y queda congelado mientras tu cliente paga. Una tasa guardada en tu servidor o en el navegador puede estar vencida.
  • Precio y liquidación son dos cosas. El pago guarda el precio (amount, en dólares) y, aparte, lo que realmente se movió (settlement, en bolívares, con la tasa que se usó). Mira precio y liquidación.

Si prefieres precios fijos en bolívares, usa currency: "VES": se cobran tal cual, sin conversión. Los euros funcionan igual que los dólares, con la tasa BCV del euro.

1. Pon tus precios en dólares

const product = await billete.products.create({
  name: "Kit de iniciación",
  currency: "USD",
  amount: 1000,
  taxBehavior: "exclusive",
});

Los montos van en la unidad menor: 1000 son USD 10,00. Los planes y los Cobros llevan su currency igual. Un checkout o un Cobro no mezclan monedas: todos sus productos deben estar en la misma (currency_mismatch), y un cupón de monto fijo está en la moneda de los precios a los que aplica.

Antes de ofrecer una moneda, comprueba que se pueda cobrar con billete.currencies.list(): cada moneda trae active y los métodos que la cobran. Que exista en los tipos (por ejemplo, USDT) no significa que esté activa.

2. Muestra el precio en bolívares como referencia

En tu catálogo puedes mostrar, junto al precio en dólares, cuánto es hoy en bolívares. Consulta las tasas desde tu servidor:

const { data: rates } = await billete.exchangeRates.list();
const usd = rates.find((rate) => rate.base === "USD" && rate.quote === "VES");

// Solo para mostrar: el monto que se cobra lo calcula Billete al pagar.
// La tasa es texto con 8 decimales; se multiplica en enteros, sin flotantes.
const toMinor = (amount: number, rate: string) => {
  const [units, decimals = ""] = rate.split(".");
  const scaled = BigInt(units + decimals.padEnd(8, "0").slice(0, 8));
  return Number((BigInt(amount) * scaled + 50_000_000n) / 100_000_000n);
};
const approximate = usd ? toMinor(product.amount, usd.rate) : null;

Cada tasa trae rate como texto decimal ("800.00000000"), su fuente ("bcv") y desde cuándo rige (effectiveAt). No la conviertas a número para multiplicar: un flotante pierde céntimos. Presenta ese monto como aproximado («≈ Bs. 8.000,00»): no incluye el IVA de un precio exclusive y la tasa puede cambiar antes del pago.

3. Cobra

El checkout alojado y la página de un Cobro ya muestran el monto en bolívares de cada método y la tasa BCV usada. Si construyes tu checkout propio, muestra el amount que devuelve paymentMethods para cada método, nunca una conversión tuya:

  • La tasa queda congelada 30 minutos desde que consultas los métodos (expiresAt de cada uno). Envía en pay el amount que mostraste.
  • Si ya no es el que se cobra, el pago no se cobra y responde exchange_rate_changed: consulta de nuevo los métodos y muestra el monto nuevo. Mira tasa congelada.
  • Si no hay una tasa oficial vigente, Billete no puede convertir el precio y responde exchange_rate_unavailable. Pide a tu cliente que lo intente en unos minutos.

Las suscripciones funcionan igual: el plan cuesta USD 10,00 al mes y cada renovación se convierte con la tasa del día en que se paga.

4. El IVA

taxBehavior dice cómo se lee cada precio: inclusive (por defecto) si ya incluye el IVA, exclusive si se le suma. El IVA es el de tu negocio y se configura en el dashboard (Configuración › Cobros › Impuestos). Si tu negocio no es contribuyente, no se cobra IVA y el total es el precio, sea cual sea taxBehavior.

Con un precio en dólares, Billete convierte cada línea (y el descuento, si hay) a la tasa del pago y calcula el IVA en bolívares sobre esa base. Para el kit de USD 10,00 más IVA del 16 %, a una tasa de 800:

PrecioLo que se cobra
BaseUSD 10,00Bs. 8.000,00
IVAUSD 1,60Bs. 1.280,00
TotalUSD 11,60Bs. 9.280,00

Por eso el total en bolívares puede diferir en algún céntimo de convertir el total en dólares. Usa siempre los totales que devuelve Billete.

5. Lo que recibes

El pago guarda las dos caras de la venta:

const payment = await billete.payments.retrieve(event.data.id);

payment.amount;                  // 1160: el precio, en payment.currency (USD)
payment.settlement?.amount;      // 928000: lo que se cobró, en settlement.currency (VES)
payment.settlement?.exchangeRate; // "800.00000000": la tasa del pago
payment.settlement?.net;         // lo que te queda después de las comisiones

Tu cliente paga el total completo y las comisiones salen de tu neto, en la moneda en que se cobró. El neto de cada pago en bolívares te llega por Pago Móvil al confirmarse: no sumes montos de monedas distintas. Un reembolso también va en bolívares, en la moneda en que se cobró, no en el precio en dólares.

EventoQué pasóQué hace tu aplicación
payment.succeededSe confirmó el pago, con su settlement.Guarda el precio y lo cobrado en bolívares para tu contabilidad.
checkout.completed / invoice.paidSe pagó el checkout o el Cobro.Entrega lo vendido.

Montos y monedas · Tasas de cambio · Monedas · Pagos