AltScore
Credit Management System (CMS)

Credit Card Flows

How the credit-card product behaves, step by step, with a diagram for each flow. Every rule here was checked against the code that runs it. For the request and response shapes see Credit Cards, Credit Lines, Card Products and Card Settings.

Interest and late fees live on the card, not on the lines

On a company card, credit lines only measure their own purchases. Interest, late fees and other charges are charged to the card. So the card can run out of room while the lines still show availability, and a card over its limit refuses every non-forced purchase, whatever the lines show. Reducing idle lines removes the warning, not the overdraft — see Fitting credit lines to the card.

The flows, in the order a card lives them:

  1. Card and billing-cycle lifecycle — statuses, cut-offs and the call sequence of a company card.
  2. Purchase on a company card through a credit line — every check, in order, and when the card refuses purchases.
  3. Interest and late fees — how they are computed and where they are charged.
  4. Fitting credit lines to the card — charges outside the lines, the warning, and shrinking or redistributing the lines.
  5. Payments — imputation, when the cupo comes back, how lines are freed, and payments directed to a line.

Card and billing-cycle lifecycle

A card account moves through four statuses: pending, enabled, disabled and closed. The status decides which operations the card accepts. Each card always has exactly one open statement, which is its current billing cycle. When the cut-off date passes, that statement is billed and the next cycle opens. Each billed statement then ends as paid, or goes overdue first and is paid later.

This page covers the two state machines, then the order of calls an integrator makes to run a company card with credit lines.

Card status

  • A new card always starts as pending. It accepts no purchases and no payments until you enable it.
  • disable also works on a pending card, so you can suspend a card before it is ever activated. enable works from pending and from disabled.
  • close works from any non-closed status, but only when the book is settled: outstanding − creditBalance must be exactly zero. Otherwise it returns 412. Closing the card does three things in the same transaction:
    • it closes every live credit line, with one card.credit-line.status-changed event per line (cause: card-closed);
    • it marks the open statement paid;
    • it makes closed final: no later call can reopen the card.
  • Every lifecycle call is idempotent. Enabling an enabled card, disabling a disabled one, or closing a closed one returns the card unchanged. Closing a closed card again also closes any credit lines left open on it.
Operationpendingenableddisabledclosed
Purchaseno (412)yesno (412)no (412)
Paymentno (412)yesyesno (412)
Purchase or payment reversalno (412)yesyesno (412)
enableyesno-opyesno (412)
disableyesyesno-opno (412)
close (net position = 0)yesyesyesno-op (closes leftover lines)
Change card limityesyesyesno (412)
Open a credit lineyesyesyesno (412)
Billing and accrual sweepsrunrunrunskipped

Suspending a card never suspends its debt. A disabled card still takes payments and reversals, and its cycles keep closing and accruing interest.

Statement status

StatusMeaningWhat moves it
openThe current cycle. Purchases, interest and late fees post here. Nothing is due yet.The cut-off.
closedBilled. dueAmount and minDue are frozen. The cycle is waiting for payment.A payment, or the accrual sweep once dueDate has passed.
overduePast dueDate and still owing. Accrues daily interest, plus a late fee if minDue was not met.A payment or reversal that brings remainingDue to zero.
paidremainingDue is zero, or the cycle billed nothing.Only a payment reversal sends it back to closed or overdue.

Cut-off. A statement is billed on the first operation after its closeDate, which is the inclusive last day of the cycle. Two things perform the cut-off:

  • The hourly BillingCron sweep.
  • A lazy rollover inside any purchase, payment, reversal or accrual that touches the card first. Because of this, an operation that arrives between sweep runs still lands on the right cycle.

At cut-off, any credit balance is applied first. If nothing is left to pay, the statement goes straight to paid. Each new cycle's dates come from the previous closeDate, never from the day the sweep runs. So if the sweep was down, its next run creates one statement per missed cycle and leaves no gaps. A card opened mid-cycle gets a short first cycle that ends at the next cut-off.

Overdue. The AccrualCron sweep moves a closed statement that still owes money to overdue once its dueDate has passed. A payment runs the same accrual first, up to the day before the payment, so interest is never lost when the sweep is late. Unpaid balances are never billed again in a later cycle. Each statement keeps its own dueAmount and paidAmount, and the interest it generates posts on whichever cycle is open at the time.

Integrator journey: company card with credit lines

In company-lines mode, a company holds one card and opens a credit line under it for each holder. The card owns everything financial: the limit, the cycle, interest, payments and the statement. Each line is a spending cap. A purchase must fit both the line's cap and the card's.

StepCallRules enforced
1PUT /v1/card-settings with mode: company-linesYou can always switch to company mode. Switching back to single returns 422 card_lines_still_open while any line is live.
2POST /v1/card-productsThe plan freezes its terms onto each card at issuance. The card needs an enabled product.
3POST /v1/card-accountsclientId is required. openedOn (YYYY-MM-DD, optional) backdates the first cycle and cannot be in the future. In single mode, a client with a non-closed card gets 422 card_client_has_card. Company mode has no such limit.
4POST …/enablepending becomes enabled. Only an enabled card can buy.
5POST …/credit-lines (one per holder)Requires company mode, or returns 422 card_mode_mismatch. The sum of live line limits must stay at or below the card limit (422 credit_line_over_assigned). No cupo can be assigned while the card is over its limit (422 card_over_limit).
6POST …/purchases with creditLineIdOnce a card has live lines, a purchase without a line returns 422 credit_line_required. The line must be enabled. The purchase must fit the line first, then the card. force books an over-limit purchase but never skips the line status check.
7GET …/credit-reliefShows how far the card is over its limit, idle cupo per line, and cupo the lines promise but the card can no longer back.
8POST …/payments (optional creditLineId)Accepted on enabled and disabled cards. Applied to unpaid statements in waterfall order. Anything left over becomes credit balance. creditLineId requires company mode.
9GET /v1/card-statements/{id}/documentThe composed statement for one cycle, with its debits, credits and totals.

Purchase on a company card through a credit line

POST /v1/card-accounts/{id}/purchases (permission card.purchase.create) books a consumption against the card. In a tenant running "mode": "company-lines", a company holds one card and spends through credit lines, one per holder. The purchase carries a creditLineId and must fit two caps: the line's, then the card's.

The checks run in a fixed order. Some run before the card account row is locked (they depend only on the request and the tenant config). The rest run under the lock, so two concurrent purchases cannot jointly overrun a cap. The first failing check answers and nothing is written.

Notes on the order:

  • The referenceId replay runs before every business check. Retrying a purchase that already went in returns it with 200, even if the card was disabled or the tenant mode changed in between. A concurrent replay that loses the insert race also resolves to 200 with the existing row.
  • The date-in-future check runs before the lock. Opening day and expiresOn need the account, so they run under it.
  • Without creditLineId, the card must have no live lines (enabled or disabled). A card with live lines in company-lines mode only spends through them. The mode is read only when the card has live lines.
  • The currency check runs before the line lookup. The lazy rollover and the card's spendable credit are resolved before both cap checks, so the purchase is measured against the correct cycle.
  • Line cap first, then card cap. The line check comes first so the error names the line. The card check still runs after a forced line breach, so one forced purchase can break both caps.
  • force skips caps only. It never skips card status, line status, opening day or expiry.
  • A purchase that fits both caps is never stamped, even when sent with force: true.

Checks and responses

Each cap refusal carries error.details.scope (line or card); see No credit: the line or the card?.

#CheckWhereFailure
0Idempotency-Key header replay (24h)before the handlercached 2xx replayed; same key with a different body: 422
1Body, date, creditLineId well formedhandler400
2referenceId present, amount > 0before lock400
3referenceId already bookedbefore lock200 existing transaction
4creditLineId only in company-lines modebefore lock422 card_mode_mismatch
5Date not after todaybefore lock422 card_tx_date_in_future
6Card account existslock404
7Card status enabledunder lock412
8Date not before opening dayunder lock422 card_tx_before_opening
9Date not after expiresOn (force does not skip)under lock422 card_expired
10No creditLineId on a card with live linesunder lock422 credit_line_required
11Currency matches the cardunder lock400
12Line belongs to this cardunder lock404
13Line enabled (force does not skip)under lock412
14Amount fits the line's availableunder lock422 insufficient_line_credit, or over-limit with force
15Amount fits the card's spendableunder lock422 insufficient_credit, or over-limit with force
—Booked—201

When the card refuses purchases

A card refuses a purchase for one of two reasons. The instrument is out of service: not enabled, expired, or the line is not enabled. Or the money does not fit: the line cap or the card cap. Only the money checks can be overridden, and only with force.

Card spendable is the card cap the purchase is checked against:

  • available = creditLimit − outstanding + creditBalance. It is derived and never stored.
  • Under terms.creditRestoration: "on-close", the cupo that payments and credit-restoring reversals freed during the open cycle is held back until the cut-off. So spendable = available − held, and a payment does not reopen the card until the cycle closes.
  • Spendable can go negative after a forced purchase. While it is negative, every non-forced purchase fails the card cap.

blocked is a signal, not a gate

GET /v1/card-accounts/{id}/credit-relief reports:

  • over: how much the card is past its limit.
  • recoverable: the idle cupo of the live lines.
  • blocked: over > 0 and recoverable ≤ over.

blocked is derived on every read and never stored. The purchase path never reads it. The actual refusal is always the cap check (insufficient_credit / insufficient_line_credit).

SituationWhat refusesWhat unblocks
Card pending / disabled412 on statusPOST …/enable. A closed card cannot be re-enabled.
Purchase date after expiresOn422 card_expiredNothing on this endpoint. force does not skip it.
Line disabled / closed412 on line statusRe-enable a disabled line. force does not skip it.
Line cap exhausted422 insufficient_line_creditA payment that releases cupo to the line, a reversal of the line's purchase, raising the line limit, or force.
Card spendable exhausted (incl. blocked)422 insufficient_creditA payment (held until the cut-off under on-close), a reversal, raising the card limit (PUT …/credit-limit), or force.
Card over its limit, raising a line422 card_over_limit on the line writePay or raise the card limit first. Lowering a line is always allowed.

Freeing idle lines does not reopen the card cap. Lowering or fitting a line (POST …/credit-lines/fit) changes what the lines promise, not the card's spendable. Its effect is to remove unbacked cupo, so lines stop showing room the card no longer has. It does not let a purchase through while the card is over its limit.

Interest and late fees (the accrual sweep)

Once a cycle is billed at its cut-off, its dueAmount is frozen and the cardholder has termDays to pay it. If money is still owing after the due date, the accrual sweep charges two things against that statement: a one-time late fee when the minimum payment was missed, and daily interest on what remains unpaid until it is paid. These charges do not change the overdue statement itself: they are posted as new transactions on the cycle that is open when they accrue, so they show up on the next bill. The sweep runs every hour but is idempotent, so each day of interest and each late fee is posted once.

Rules

  • Due date = cut-off + termDays; the due date itself is the last day to pay without charges.
  • Minimum payment = min(dueAmount, max(minPaymentPercent x dueAmount, minPaymentFloor)), frozen at cut-off.
  • Late fee: evaluated once, the first sweep after the due date. If payments dated on or before the due date did not reach the minimum, one charge of penaltyRate % of what was still owed at the due date. Reference pen:{statementId}.
  • Interest: for every day after the due date, interestRate prorated to one day ({"period":360,"rate":"36"} = 0.1% per day) on dueAmount minus payments dated up to that day. Reference int:{statementId}:@YYYYMMDD.
  • Tax (IVA): interestTax on interest; penaltyTax on the late fee (inherits interestTax when absent). Computed per charge and added on top: the transaction amount is gross and taxAmount shows the tax inside it.
  • Where charges land: on the cycle open when they accrue, with metadata.sourceStatementId pointing at the overdue cycle. They are billed at the next cut-off and, if that bill goes unpaid, accrue interest as part of it.
  • Card, not credit line: in company mode, interest and late fees are charged to the card account. They never use up a credit line, which only counts purchases and reversals.
  • Stopping and corrections: a payment that zeroes the statement marks it paid and interest stops. A backdated payment (dated before the days already charged, or covering the minimum by the due date) gives back the excess through a compensating reversal (lpc:...). Charges are never edited.

Worked example (termDays 10, minPaymentPercent 10, penaltyRate 5%, interestRate 360/36, interestTax 21%; illustrative figures)

DateEventCharge (net + tax = gross)
Mar 14Cut-off bills 10,000.00; minDue 1,000.00; due date Mar 24—
Mar 24Nothing paid—
Mar 25Statement becomes overdue; minimum missed: late fee 5% x 10,000500.00 + 105.00 = 605.00
Mar 25–28Daily interest 0.1% x 10,00010.00 + 2.10 = 12.10 per day
Mar 28Cardholder pays 10,000.00, statement paidinterest stops
Apr 14Next cut-off bills 605.00 + 4 x 12.10 = 653.40 of finance charges—

Mar 28 is charged if that day's sweep ran before the payment was registered (the usual case with an hourly sweep). A payment registered before the sweep cancels that day's interest.

Fitting credit lines to the card (credit-relief and fit)

On a company card, the card owns everything financial: limit, cycle, interest, late fees and payments. The credit lines are only spending caps. A line's consumed counts its own purchases only. Interest, late fees and other card-level charges post to the card, not to any line.

So once the card's whole limit is assigned to lines, those charges eat room on the card that no line knows about. The lines keep showing available cupo that the card no longer has. GET /v1/card-accounts/{id}/credit-relief reports this gap as unbacked. POST /v1/card-accounts/{id}/credit-lines/fit lowers the lines until it is gone.

1. The money picture

Card limit 10,000. Four lines whose limits add up to exactly 10,000, since the sum of live line limits can never exceed the card limit. The lines spend 9,600. One line is 600 over its own cap because of a forced purchase. The card is also charged 1,616.77 of interest and late fees.

What credit-relief returns for this card:

FieldValueHow it is computed
over1,216.77−(card available), when negative
outsideLines1,616.77card limit − card available − Σ line consumption
idle / recoverable1,000.00Σ (limit − used) of the live lines with positive idle. Only Fleet South qualifies
unbacked1,000.00recoverable − max(card available, 0)
blockedtrueover > 0 and recoverable ≤ over. Freeing all idle cupo still would not cover the overdraft
fitFleet South: cut 1,000 → 2,000see below

Because the line cap is checked first, a purchase on Fleet South is not refused by the line, which shows 1,000 of room. It is refused by the card, which has none. That is what the unbacked warning means.

2. What the operator or integrator does

Fit removes the warning (unbacked). It does not clear the overdraft. In the example the card stays 1,216.77 over after the fit, and with no idle cupo left it is still blocked. Only a payment or a higher card limit gets it back under the limit.

3. What POST …/credit-lines/fit does on the server

How the plan is built (planLineFit):

  • Only idle cupo (limit − used > 0) is taken, so no line goes below what it spent. Lines at or over their cap are left alone.
  • The cut is proportional to each line's idle: cut = idle / recoverable × unbacked, rounded per line. If unbacked is at least recoverable, every idle line loses all of its idle.
  • Rounding cents go to the line with the largest idle, never past its idle. The cuts add up to unbacked exactly.
  • A line whose suggested limit would be 0 (no spending and all of it unbacked) is marked closeSuggested. A limit cannot be 0, and fit never closes a line. Close it yourself with PUT …/status.
  • Idempotent: once the lines fit, a second call changes nothing and emits no events.
  • Works in any tenant mode and while the card is over its limit, because lowering is the way out.

4. Gates on line and card limits

  • Disabled lines still hold their cupo, because a suspended line is not a surrendered one. Closed lines give it back. A closed line cannot be reopened.
  • Raising a line or opening one is refused with card_over_limit while the card is over its limit. Lowering a line is always allowed, even below its own consumption. Fit itself never cuts below consumption.
  • card_over_limit gates lines only. Raising the card's own limit has no over-limit gate.
  • Opening and raising lines also require the tenant to be in company-lines mode. Otherwise they return 422 card_mode_mismatch. Lowering, closing and fit work in any mode.

5. Worked examples: lines before and after fit

A. Charges on top of a fully assigned card (the scenario above). Card limit 10,000, card available −1,216.77, unbacked 1,000.

LineLimit beforeUsedIdleCutLimit after
Fleet North3,000.003,000.000.00—3,000.00
Fleet South3,000.002,000.001,000.001,000.002,000.00
Sales2,000.002,600.00−600.00—2,000.00
Management2,000.002,000.000.00—2,000.00
CardΣ 10,000.009,600.00 + 1,616.77 chargesΣ 9,000.00 · unbacked 0 · still over 1,216.77

B. Proportional split with no overdraft. Card limit 10,000. Charges have already used 3,000, so the card can still spend 5,000. The lines promise 8,000 of idle cupo, so 3,000 is unbacked.

LineLimit beforeUsedIdleShare of idleCutLimit after
A5,000.001,000.004,000.0050%1,500.003,500.00
B5,000.001,000.004,000.0050%1,500.003,500.00

After the fit, idle is 2,500 + 2,500 = 5,000, which is exactly what the card can spend.

Payments: allocation, credit restoration and directed payments

A payment on a credit card does two separate things, and they are decided by three separate product settings frozen on the account's terms:

  • Allocation (terms.paymentAllocation) decides which debt the money settles: which billed statements, and within them, consumption or finance charges.
  • Line restoration (terms.lineRestoration, company-lines mode only) decides whose cupo comes back: how much of what each credit line consumed is freed.
  • Credit restoration (terms.creditRestoration) decides when the freed cupo can be spent again: immediately, or only after the cycle's cut-off.

A payment can optionally be directed to one credit line with creditLineId. Directing a payment never changes the allocation; it only changes who gets the cupo back first.

How a payment is registered

Key points:

  • Idempotency. referenceId is the caller's key: replaying it returns the existing payment with 200 and changes nothing.
  • Catch-up accrual first. Before applying the payment, the service accrues interest up to the day before the payment date. Otherwise a payment that settles a cycle would take it out of the unpaid list and the days since the last sweep would never be charged.
  • Allocation waterfall. oldest-cycle (default) settles each unpaid statement in full, oldest cut-off first. charges-first first covers the interest and late fees of every unpaid statement, oldest first, and only then consumption. A statement that reaches zero becomes paid, which stops its daily interest. Anything left over becomes credit balance.
  • The line release is decided once. It is computed with what was owed right before the payment (owedBefore = outstanding − creditBalance) and stored on the payment as metadata.lineReleases. It is never recomputed.
  • Backdated payments. If the payment date is earlier than charges the accrual sweep already posted, those charges are compensated in the same transaction.

How a payment frees cupo on the credit lines

Undirected payment. The freed total is min(payment, owed) / owed applied to every line's consumption. Interest and late fees are part of owed but belong to the card, not to any line, so they dilute the release: with 11,216.77 owed and 9,500.00 of line consumption, a 500.00 payment frees about 423 across the lines, not 500. The policy (proportional, oldest-first, newest-first) only decides who gets that total, never how much it is.

Directed payment. The named line is freed first: up to the payment amount, capped by what the line consumed and by what was owed. Whatever is left of the payment is treated as a normal payment over the remaining debt and frees the other lines under lineRestoration. If the named line holds no consumption, the whole payment behaves as an undirected one.

The line measures cupo, not accounting debt

The release to a directed line does not look at which purchases the payment settled. Under charges-first, a 500.00 payment can be imputed entirely to interest and late fees, with nothing applied to the line's purchases, and the line still gets 500.00 of cupo back. This is intended: a credit line is a spending cap, not a ledger. The real debt (purchases, interest and late fees) stays on the card and keeps following paymentAllocation.

Other rules:

  • The line must belong to this card (404) and must not be closed (412). A disabled line is accepted: a suspended line can still be paid.
  • creditLineId on a payment only exists in company-lines mode; in any other mode the request fails with 422 card_mode_mismatch.
  • The payment row keeps creditLineId. The statement document shows the line's label on the payment row, but byCreditLine stays consumption-only: a directed payment is never counted as a line's spend.
  • Reversing the payment undoes its release: reversed payments stop counting in the line's consumption.
  • Under creditRestoration: "on-close", the cupo a payment frees on a line (directed or not) only becomes spendable after the cycle's cut-off, exactly like the card's own available credit.

Worked example

Company card in company-lines mode, lineRestoration: "proportional". Juan's line holds 1,500.00 of consumption and Ana's 8,000.00. Those 9,500.00 of purchases were billed on the oldest unpaid cycle; 1,716.77 of interest and late fees were billed on later cycles. Owed before the payment: 11,216.77. All figures are illustrative.

PaymentpaymentAllocationWhere the money is imputedJuan freedAna freedJuan still holdsAna still holds
500.00, undirectedoldest-cycle500.00 to the oldest cycle (purchases)66.86356.611,433.147,643.39
500.00, undirectedcharges-first500.00 to interest and late fees66.86356.611,433.147,643.39
500.00, directed to Juanoldest-cycle500.00 to the oldest cycle (purchases)500.000.001,000.008,000.00
500.00, directed to Juancharges-first500.00 to interest and late fees, 0.00 to purchases500.000.001,000.008,000.00
2,000.00, directed to Juancharges-first1,716.77 to charges, 283.23 to purchases1,500.00411.660.007,588.34

How to read it:

  • The release column never changes with paymentAllocation: allocation decides what debt is settled, release decides whose cupo comes back.
  • Undirected: 500 / 11,216.77 = 4.4576% of each line's consumption, rounded per line. The charges dilute it to 423.47 freed in total.
  • Directed to Juan: Juan gets the full 500.00, Ana nothing, even when every peso went to interest and late fees.
  • 2,000.00 directed to Juan: Juan is freed in full (1,500.00). The remaining 500.00 is a normal payment over 11,216.77 − 1,500.00 = 9,716.77 and frees 500 / 9,716.77 of Ana's 8,000.00.
  • In every 500.00 case the card's debt drops to 10,716.77.

Request: a payment directed to a credit line

POST /v1/card-accounts/{id}/payments
{
  "referenceId": "pay-0001",
  "amount": { "amount": "500.00", "currency": "ARS" },
  "creditLineId": "00000000-0000-4000-8000-000000000001"
}

date (YYYY-MM-DD, defaults to today) and metadata are optional. Omit creditLineId for an undirected payment. The response is the payment transaction: applications shows where the money was imputed, creditLineId echoes the line, and metadata.lineReleases records the cupo freed per line, for example { "<creditLineId>": "500.00" }. Replaying the same referenceId returns 200 with the original payment.