El dinero en Zaroz son dos cosas: facturas (lo que debes) y un monedero (crédito que tienes). Cómo una compra se convierte en factura está en Suscripciones y facturación. Esta página es la parte del dinero, llamada a llamada. Los ejemplos usan el ayudante de Usar la API de Zaroz. Todos los importes son céntimos enteros en la moneda de la factura.
Leer el monedero
El monedero es de la organización, y todos sus miembros leen el mismo saldo. El tuyo es el de tu organización personal.
curl
Code
curl -sS "$ZAROZ_API/me/wallet" -H "$AUTH"curl -sS "$ZAROZ_API/organizations/$ORG/wallet" -H "$AUTH"curl -sS "$ZAROZ_API/me/wallet/entries?page=1&page_size=25" -H "$AUTH" # el libro, lo más nuevo primero
import { call } from "./zaroz";const wallet = await call("GET", "/me/wallet");for (const b of wallet.body.balances) { console.log(b.currency, "gastable", b.spendable_cents / 100, "promo", b.promo_cents / 100);}const ledger = await call("GET", "/me/wallet/entries?page_size=25");for (const e of ledger.body.data) console.log(e.created_at, e.reason, e.amount_cents);
Python
Code
from zaroz import call_, wallet = call("GET", "/me/wallet")for b in wallet["balances"]: print(b["currency"], "gastable", b["spendable_cents"] / 100, "promo", b["promo_cents"] / 100)_, ledger = call("GET", "/me/wallet/entries?page_size=25")for e in ledger["data"]: print(e["created_at"], e["reason"], e["amount_cents"])
Solo se devuelven los saldos distintos de cero, así que un monedero que nunca se recargó responde una lista balances vacía. Trata una moneda ausente como cero.
Qué significan las cifras
Campo
Significado
spendable_cents
Lo que un pago con monedero puede usar ahora mismo. Úsalo para decidir si una factura se puede pagar, no amount_cents
real_cents
Dinero equivalente a efectivo: recargas, reembolsos liquidados al monedero
promo_cents
Crédito promocional. Nunca es efectivo y no se puede retirar. No se gasta como efectivo en un pago: se aplica automáticamente como línea de descuento al emitir una factura (y al pagar con el monedero una factura sin pagar)
legacy_cents
Dinero antiguo aún sin clasificar; un pago con monedero no puede gastarlo
amount_cents
Todo lo anterior sumado. Solo para conciliar
El libro no tiene columna de saldo acumulado: cada entrada es un movimiento con signo (positivo acredita, negativo debita) con un reason como top_up_pay_pal, redeemed_code, invoice_autopay, invoice_refund o promo_grant.
Añadir fondos
Primero pregunta qué proveedores pueden aceptar una recarga ahora y muestra solo esos:
const topup = await call("POST", "/me/wallet/top-ups", { amount_cents: 2500, provider: "paypal" });console.log("Envía al cliente a", topup.body.checkout_url);// no se acredita nada hasta que el proveedor confirma; consultafor (;;) { const t = await call("GET", `/me/wallet/top-ups/${topup.body.id}`); if (["credited", "expired", "failed", "review_required", "reversed"].includes(t.body.status)) { console.log(t.body.status); break; } await new Promise((r) => setTimeout(r, 5000));}
Python
Code
import timefrom zaroz import call_, topup = call("POST", "/me/wallet/top-ups", {"amount_cents": 2500, "provider": "paypal"})print("Envía al cliente a", topup["checkout_url"])while True: # no se acredita nada hasta que el proveedor confirma _, t = call("GET", f"/me/wallet/top-ups/{topup['id']}") if t["status"] in ("credited", "expired", "failed", "review_required", "reversed"): print(t["status"]) break time.sleep(5)
provider es paypal o nowpayments (criptomonedas).
amount_cents debe ser uno de los importes fijos en EUR: 2500, 5000, 10000, 25000, 100000. Cualquier otro se rechaza con invalid-field-value.
La llamada no acredita nada. El monedero se acredita una vez, cuando el proveedor confirma el pago. Solo credited significa que llegó el dinero; expired, failed, review_required y reversed son terminales.
Reintentar una recarga tras un fallo de tiempo inicia un segundo pago independiente. Ninguno mueve dinero hasta que se paga.
Un proveedor sin configurar o que no responde da 503 y no se cobró nada.
Un token de organización necesita organizations.wallet.top_up para esto.
Canjear un código de monedero
Un código de monedero (un regalo o sorteo) acredita un monedero, una sola vez. preview no necesita cuenta, de modo que un enlace de reclamación puede mostrar lo que vale el código antes de iniciar sesión.
Sea cual sea el motivo del fallo (no existe, ya se usó, se revocó, caducó o se alcanzó un límite por persona), la respuesta es la misma invalid-field-value. Es deliberado: impide sondear qué códigos existen. Envía siempre un Idempotency-Key, para que un reintento tras un fallo de tiempo devuelva el primer crédito en lugar de un rechazo.
Facturas
curl
Code
curl -sS "$ZAROZ_API/billing/invoices?page=1&page_size=25" -H "$AUTH" # todas las organizaciones que vescurl -sS "$ZAROZ_API/organizations/$ORG/invoices?status=pending" -H "$AUTH"curl -sS "$ZAROZ_API/billing/invoices/$INVOICE" -H "$AUTH" # con sus líneascurl -sS "$ZAROZ_API/billing/invoices/open-summary" -H "$AUTH" # cuántas, vencidas, total adeudadocurl -sS "$ZAROZ_API/subscriptions/$SUBSCRIPTION/invoices" -H "$AUTH"
TypeScript
Code
const open = await call("GET", "/billing/invoices/open-summary");console.log(`${open.body.count} abiertas, ${open.body.overdue_count} vencidas, total ${open.body.total_cents}`);const invoice = await call("GET", `/billing/invoices/${INVOICE}`);for (const line of invoice.body.lines) console.log(line.description, line.amount_cents, line.project_name);
Python
Code
_, open_ = call("GET", "/billing/invoices/open-summary")print(open_["count"], "abiertas,", open_["overdue_count"], "vencidas, total", open_["total_cents"])_, invoice = call("GET", f"/billing/invoices/{INVOICE}")for line in invoice["lines"]: print(line["description"], line["amount_cents"], line["project_name"])
El status de una factura es pending, paid, failed, refunded o cancelled; su kind es initial, renewal, resize, admin_resize o trial_purchase. total_amount_cents incluye impuestos (tax_amount_cents, tax_rate, tax_label). Todos los miembros de la organización pueden leer sus facturas; pagar requiere el rol Owner, Admin o Billing.
Pagar una factura
Tres formas de liquidar una factura pending.
Con el monedero. Es inmediato y necesita que spendable_cents cubra la factura:
const paid = await call("POST", `/billing/invoices/${INVOICE}/pay-with-wallet`, undefined, { "Idempotency-Key": randomUUID(),});if (paid.status === 422) console.log("saldo gastable insuficiente, o ya pagada");
Python
Code
status, paid = call("POST", f"/billing/invoices/{INVOICE}/pay-with-wallet", headers={"Idempotency-Key": str(uuid.uuid4())})if status == 422: print("saldo gastable insuficiente, o ya pagada")
Un monedero que no cubre la factura da 422 indicando el saldo y el importe necesario (no se intentó nada). Una factura ya pagada también da 422. Un pago con tarjeta o PayPal en curso responde 409; no se cobró nada. Pagar es la única llamada donde un reintento a ciegas podría costar dinero real dos veces, por eso importa el Idempotency-Key. Un token de organización necesita organizations.wallet.spend.
Con tarjeta (Mollie) o PayPal. Ambos devuelven una página alojada a la que enviar al cliente:
Code
curl -sS -X POST "$ZAROZ_API/billing/invoices/$INVOICE/checkout/mollie" -H "$AUTH"curl -sS -X POST "$ZAROZ_API/billing/invoices/$INVOICE/checkout/paypal" -H "$AUTH"# {"checkout_url": "https://..."}
Code
const { body } = await call("POST", `/billing/invoices/${INVOICE}/checkout/paypal`);console.log("Abre", body.checkout_url);
Code
_, body = call("POST", f"/billing/invoices/{INVOICE}/checkout/paypal")print("Abre", body["checkout_url"])
Cuando el cliente termina, el proveedor lo devuelve al panel; la factura pasa a paid cuando el proveedor lo confirma. Consulta GET /billing/invoices/{id} en lugar de fiarte de la redirección. Comprueba antes qué ofrece el despliegue (mollie, paypal): un proveedor sin configurar responde 501 capability-not-available.
Pago automático
Por defecto el monedero paga solo tus facturas de renovación cuando tiene saldo suficiente. Desactívalo si prefieres aprobar cada pago:
Activar el pago automático autoriza a la plataforma a gastar el monedero en cada renovación, por lo que requiere la autoridad de gasto (Owner o Admin), no solo el derecho a recargar.
Si no pagas
Una factura vencida no desaparece. El estado de tu organización lo refleja y puede restringir compras nuevas; GET /organizations/{id}/standing te dice si estás restringido y, a los propietarios, por qué.