Card Products API
A card product is a plan: the financial contract a credit card is issued under — cut-off cadence, days to pay, interest and late-fee rates, minimum payment and card validity.
The CMS Base URL is used (see introduction).
Terms are frozen at issuance
When a card is opened, the plan's terms are copied onto the account.
Editing a plan later never rewrites cards already issued, and disabling a plan
only stops new cards from being opened under it.
The Card Product Object
Attributes
| Attribute | Description | Type |
|---|---|---|
id | Card product id | UUID |
name | Commercial name of the plan | String |
status | enabled or disabled — disabled plans cannot open new cards | String |
isDefault | The plan used when a card is opened without productId | Boolean |
terms | See Card Terms | Object |
Card Terms
| Field | Description | Type |
|---|---|---|
billingPeriod | Cut-off cadence. monthDays (1–31) and/or weekDays (0=Sunday) are the days a cycle can start (the cut-off is the day before); unit+count set the length when unconstrained. | Object |
termDays | Days from the cut-off to the due date | Integer |
interestRate | Nominal rate charged daily on unpaid statement balances. {"period":360,"rate":"36"} = 36% nominal yearly ⇒ 0.1% per day. | Object |
penaltyRate | One-shot late fee as a % of the remaining due as of the due date, charged only when the minimum payment was missed | Object |
minPaymentPercent | Minimum payment as a % of the billed amount | String |
minPaymentFloor | Optional absolute floor for the minimum (capped at the billed amount) | Money |
interestTax | Tax (VAT) on each interest charge, as a % of it. Absent or zero = untaxed. | String |
penaltyTax | Tax on the late fee. Absent inherits interestTax; set it explicitly — including to "0" — when the late fee is taxed differently. | String |
validityYears | Card validity: the account's expiresOn = opening date + this. Defaults to 3. | Integer |
currency | Currency of every card issued under the plan (ISO 4217) | String |
paymentAllocation | Order a payment is imputed across unpaid statements: oldest-cycle (default) or charges-first. See Payment policies. | String |
creditRestoration | WHEN a payment gives the cupo back: immediate (default) or on-close. See Payment policies. | String |
lineRestoration | Company mode only: WHICH credit lines a payment frees: proportional (default), oldest-first or newest-first. See Credit Lines. | String |
Unknown keys are rejected
Terms are decoded strictly: a key the contract does not have answers 400
naming it, instead of being dropped. That includes the keys inside a rate:
interestRate and penaltyRate carry the value under rate
({"period": 360, "rate": "36"}), and {"period": 360, "value": "36"} is
rejected rather than creating a 0% plan. currency must be an ISO 4217 code.
Payment policies
Three terms decide what a payment does. Like every term, they are frozen onto the card when it is issued, so changing the plan never re-imputes existing cards.
| Term | Values | What it decides |
|---|---|---|
paymentAllocation | oldest-cycle (default), charges-first | Which debt a payment settles first. oldest-cycle settles each unpaid statement in full, oldest first. charges-first covers the interest and late fees of every unpaid statement first, then the consumption. |
creditRestoration | immediate (default), on-close | When a payment gives the cupo back. immediate: a revolving limit. on-close: a per-period allowance — the debt drops at once, but the paid cupo is usable again only after the next cut-off. |
lineRestoration | proportional (default), oldest-first, newest-first | Company mode: whose line gets its cupo back. It never changes how much is freed. |
charges-first costs the cardholder more interest
It collects interest and late fees early but leaves more principal alive, and the principal is the base of the daily interest. Pick it when a regulation or accounting rule requires charges to be settled first, not as a neutral default.
on-close needs to be explained on the statement
A cardholder who pays mid-cycle sees the debt drop and the available credit stay put until the cut-off. That is the intent of the policy, not a bug.
A monthly card whose cycles start on the 15th and gives 10 days to pay is
{"billingPeriod": {"unit": "day", "count": 1, "monthDays": [15]}, "termDays": 10}:
cycles run from the 15th to the 14th (the cut-off), and the due date is the 24th.
Cut-off on the last day of the month: use monthDays: [1]. Cycles run from the
1st to the month's last day (28, 29, 30 or 31). A day a month does not have (29,
30 or 31 in a shorter month) is clamped to that month's last day: [31] starts
cycles on Jan 31, Feb 28, Mar 31, Apr 30… so its cut-offs fall on Feb 27, Mar 30,
Apr 29… — not at month end. Products and accounts configured with 29, 30 or 31
return a warnings array explaining this.
Endpoints
Create a Card Product
| Field | Description | Type |
|---|---|---|
name | Commercial name | String |
isDefault | Make it the tenant's default plan | Boolean |
terms | The plan's terms — required | Object |
Returns 201 with the Card Product. 400 when the terms are inconsistent (for
example a negative termDays, a minPaymentPercent outside 0–100, or a
minPaymentFloor in a different currency than the plan).
List / Get Card Products
Update a Card Product
name and isDefault are optional (absent = unchanged). terms is
required: send only the keys you want to change, and the rest is filled from
the plan's current terms — "terms": {} changes nothing. Existing cards keep the
terms they were issued with.
Enable or Disable a Card Product
Body: { "status": "enabled" } or { "status": "disabled" }.
Permissions
| Permission | Grants |
|---|---|
card.settings.read | list and read plans |
card.settings.write | create, update, enable/disable |
Error Handling
| Status | When |
|---|---|
400 | Invalid terms, an unknown key in the terms, a non-ISO currency, or a missing name |
404 | Unknown plan |
412 | Opening a card under a disabled plan |
409 | Concurrent modification of the same plan (retry with the fresh version) |