Skip to content
In this section

Credits

Stored-value balances, their append-only ledger and drawdown on issued invoices.

Stored value is a capability your deployment switches on. While it is off, every endpoint below answers 501 with billing credits are not enabled — and that is the honest answer, because with it off the billing engine does not draw credit into invoices at all, so any balance shown would never be consumed.

Credits are stored value held against a contract — customer prepayments, promotional grants, goodwill. Balances are derived from an append-only ledger; drawdown happens automatically when an invoice is issued against a contract holding credit (visible on the invoice as creditAppliedMinor).

Wallet balance, credit balance and customer balance. A wallet balance is money a seller owns and is paid out from (wallets). A credit balance is stored value a buyer holds and spends instead of cash; it lives in the credit ledger, anchored either on a billing contract (the merchant's customer) or on a platform consumer (the coupon wallet). A customer balance is that credit balance for one consumer. The two stored-value systems never hold the same money: credit becomes wallet money only when an order it funded settles to the seller.

Endpoints

  • GET /billing-api/v1/credits — your balances across all contracts, one row per currency and credit type:
{
  "balances": [
    {"currency": "EUR", "creditType": "purchased", "balanceMinor": 250000, "isLiability": true}
  ]
}

creditType is one of promotional, purchased, manual, gift, enterprise, ai_token, marketplace or proration. isLiability marks the paid-for types (purchased, enterprise, proration) — unearned revenue you owe as service. Those never expire; granted credit may. proration is minted by the engine rather than granted by you: when a mid-term subscription amendment credits your customer more than the invoice it lands on can absorb, the remainder becomes a proration lot — money the customer already paid for service not rendered — and the next document draws it down.

  • GET /billing-api/v1/contracts/{contractId}/credits — one contract's balances (always complete) plus a page of its ledger history. limit sets the page size (1–100, default 20); while hasMore is true, pass the returned nextCursor back as cursor to walk older entries:
{
  "balances": [ ... ],
  "hasMore": true,
  "nextCursor": 1180,
  "nextBeforeId": 1180,
  "entries": [
    {
      "id": 1201,
      "kind": "topup",
      "creditType": "purchased",
      "signedDeltaMinor": 250000,
      "currency": "EUR",
      "invoiceId": null,
      "reason": "annual prepayment",
      "occurredAt": "2026-08-01T09:30:00Z"
    }
  ]
}

Entries are newest-first. kind is topup, deduction, expiry or reversal — the last one returns a deduction to the customer when the invoice it funded is cancelled. signedDeltaMinor is positive for topup and reversal, negative for deduction and expiry, and invoiceId links a deduction (and the reversal that undoes it) to the document it funded.

  • POST /billing-api/v1/contracts/{contractId}/credits/top-up — grant a credit lot. This is the only way credit enters the ledger; deduction, expiry and reversal rows are the engine's and have no public route.
curl -s -X POST "$FYNEX_API_BASE/contracts/42/credits/top-up" \
  -H "Authorization: Bearer $FYNEX_API_KEY" \
  -H "Idempotency-Key: 3f0b6a1e-9c1d-4f10-9f2b-6f2a1c1e6a1e" \
  -H "Content-Type: application/json" \
  -d '{"creditType":"purchased","amountMinor":250000,"currency":"EUR","reason":"annual prepayment"}'

Idempotency-Key is required, and here the body is compared: the same key with a different contract, amountMinor or currency answers 422 instead of returning the first grant, because a top-up that never happened must not look like one that did. A matching replay answers 200 with the original entry; the first call answers 201.

currency must equal the contract's own — credit is never converted. An expiresAt is allowed only on granted credit: purchased and enterprise were paid for, and money someone paid must not evaporate on a calendar date. sellerCustomerId is optional attribution and must name one of your customers (POST /billing-api/v1/customers); the contract remains the balance anchor.

Correcting a grant is not an edit — the ledger is append-only. Contact support for a correcting entry.