Payment allocation ( payment_allocation )

A payment_allocation traces how a receipt or disbursement is allocated across one or more financial documents. It is the object linking a psp_payment or a payment and the invoices to the document it settles.

Role

Whenever a payment is reconciled with one or more invoices, a payment_allocation is created to materialize that allocation. It answers: how much of which payment was applied to which invoice?

The allocation is a two-level object:

  • L'header (pal_) identifies the source and its overall allocation status (partial or complete).

  • The lignes (pai_) detail each individual allocation — how much was applied to which target (invoice, credit note, order, etc.).

Creating an allocation has immediate side effects: update of the settlement_status of the relevant financial documents and update of the status of the source payment. Invoice lifecycle remains independent.

Identifier and structure

The header uses prefix pal_ ; each line uses prefix pai_.

JSON
"payment_allocation":{12 items
"object":"payment_allocation"
"id":"pal_3c8f1a9b2d4e7f6a"
"merchant_id":"mer_1a2b3c4d5e6f7a8b"
"source_type":"psp_payment"
"source_id":"psp_7e4b2d9f1c3a8e5f"
"source_reference":null
"reverses_allocation_id":null
"reversed_by_allocation_id":null
"status":"complete"
"created_at":"2026-06-17T14:30:00.000Z"
"updated_at":"2026-06-17T14:30:00.000Z"
"items":[1 item
0:{...}8 items
]
}
{
"object": "payment_allocation",
"id": "pal_3c8f1a9b2d4e7f6a",
"merchant_id": "mer_1a2b3c4d5e6f7a8b",
"source_type": "psp_payment",
"source_id": "psp_7e4b2d9f1c3a8e5f",
"source_reference": null,
"reverses_allocation_id": null,
"reversed_by_allocation_id": null,
"status": "complete",
"created_at": "2026-06-17T14:30:00.000Z",
"updated_at": "2026-06-17T14:30:00.000Z",
"items": [
  {
    "object": "payment_allocation_item",
    "id": "pai_1a3f2b9c4d8e5f7a",
    "payment_allocation_id": "pal_3c8f1a9b2d4e7f6a",
    "target_type": "invoice",
    "target_id": "inv_4a7b2e9f1c3d8a5e",
    "amount": 120000,
    "currency": "eur",
    "created_at": "2026-06-17T14:30:00.000Z"
  }
]
}

Header fields

FieldTypeDescription
idstringAllocation identifier (prefix `pal_`).
objectstringAlways "payment_allocation".
merchant_idstringOwning merchant.
source_typeenumSource type: `psp_payment`, `payment`, or `supplier_payment`.
source_idstringSource-object identifier (`psp_…`, `pay_…`, `spay_…`).
source_referencestring | nullOptional source reference used notably for idempotency.
reverses_allocation_idstring | nullAllocation compensated by this one when this is a reversal.
reversed_by_allocation_idstring | nullCompensating allocation that reversed this one, if any.
statusenum`partial` or `complete`.
created_atdatetimeCreation date.
updated_atdatetimeLast update date.

Lignes d'imputation

Each line (payment_allocation_item) describes allocation of a sub-amount from the source to one specific target document. An allocation may have several lines when the payment covers several invoices.

FieldTypeDescription
idstringLine identifier (prefix `pai_`).
objectstringAlways "payment_allocation_item".
payment_allocation_idstringAllocation parente (pal_…).
target_typeenumTarget type: `invoice`, `credit_note`, `order`, `unallocated` (AR) or `supplier_invoice`, `supplier_credit_note`, `purchase_order`, `unallocated` (AP).
target_idstringTarget identifier (`inv_…`, `ord_…`, `cmp_…` when `unallocated`).
amountintegerAllocated amount in the currency's minor unit. Positive for invoices, negative for credit notes.
currencystringCurrency (lowercase ISO 4217). Must match source currency.
created_atdatetimeCreation date.
Credit-note amounts: negative

For a line targeting a credit_note, the amount field is negative — the credit note offsets part of the amount to settle rather than directly reducing it. The algebraic sum of the lines gives the net allocated amount.

Lines are available through GET /v1/payment-allocations/:id (returned in the parent object) or through the GET /v1/payment-allocations?source_id=psp_….

Status

filter. The header status reflects whether the full source amount has been allocated.

StatusMeaning
partial

The sum of lines is lower than the source amount — part of the payment remains unallocated. The source payment moves to partially_matched.

complete

The sum of lines equals the source amount — the payment is fully reconciled. The source payment moves to matched.

The status is calculated at creation

A payment_allocation is immutable after creation. Its status is determined at POST time from the total lines relative to the source amount. To allocate the remainder of a partially_matchedpayment, create a new allocation on the same source payment.

Sources and targets

Source types

source_typeConstraintUsage
psp_paymentstatus = succeeded, buyer_id requiredCollected PSP payment — automatic allocation to buyer invoices.
paymentstatus ∈ {pending, partially_matched}Platform payment being reconciled — manual or process-driven allocation.
supplier_paymentstatus ∈ {pending, scheduled, executed}Outbound disbursement — allocation to supplier invoices (AP flow).

Target types

target_typeFluxDescription
invoiceAROpen buyer invoice. The amount reduces the balance due.
credit_noteARBuyer credit note. The negative amount increases the amount to settle.
orderARAdvance on an order before invoice issuance.
unallocatedAR / APUnallocated provision — `target_id` is the company identifier. Used for advances with no known target.
supplier_invoiceAPSupplier invoice. The amount reduces payable debt.
supplier_credit_noteAPSupplier credit note.
purchase_orderAPAdvance on a purchase order.

Side effects on targets

Creating an allocation immediately updates statuses of the relevant objects.

Target / affected objectEffet
invoice`settlement_status` → `partially_paid` or `paid` according to total applied. Document `status` remains unchanged.
credit_note`credit_note.applied` event emitted. No status change.
order`order.advance_received` event emitted. No status change.
payment (source)`status` → `matched` or `partially_matched` according to total amount allocated.
supplier_invoice`settlement_status` → `scheduled`, `partially_paid`, or `paid` according to disbursement state. Document `status` remains unchanged.

Creation

A payment_allocation is created through POST /v1/payment-allocations. The request describes the source and the list of allocation lines.

HTTP
POST /v1/payment-allocations
{3 items
"source_type":"psp_payment"
"source_id":"psp_7e4b2d9f1c3a8e5f"
"items":[1 item
0:{...}4 items
]
}
{
"source_type": "psp_payment",
"source_id": "psp_7e4b2d9f1c3a8e5f",
"items": [
  {
    "target_type": "invoice",
    "target_id": "inv_4a7b2e9f1c3d8a5e",
    "amount": 120000,
    "currency": "eur"
  }
]
}

The platform validates that:

  • The source is in an eligible status (see source table).
  • All targets belong to the same merchant and use the same currency as the source.
  • No target is over-allocated (total applied ≤ document amount).
  • The sum of lines does not exceed the source amount.
  • AR targets belong to the same buyer as the source when the source carries a buyer_id.

The read endpoints:

HTTP
GET /v1/payment-allocations/:id
GET /v1/payment-allocations?source_type=psp_payment&source_id=psp_7e4b
GET /v1/payment-allocations?target_type=invoice&target_id=inv_4a7b

In processes

In practice, payment_allocation are not created manually — they are produced by reconciliation nodes.

NodeProduced source_typeRole
reconcile_paymentpayment or psp_payment

Receives a bank or PSP payment and an allocation proposal (output of propose_payment_allocation), then creates the payment_allocation using the corresponding source type.

The usual flow for a PSP receipt is: psp_payment.succeeded → propose_payment_allocation → reconcile_payment → payment_allocation created → invoices settled.

Correct an allocation

An allocation is an immutable fact: it is neither edited nor deleted. To correct it, reverse it. contre-passe.

HTTP
POST /v1/payment-allocations/:id/reverse

The call creates a compensating allocation — the exact mirror of the named allocation, aggregated by target, with opposite amounts. No breakdown is chosen. All relevant statuses are recalculated: source payment, invoices, credit notes, refund rollups.

Correcting an amount therefore happens in two steps: reverse then a new allocation. Reversal frees source capacity, so reallocating is an ordinary operation — there is deliberately no reversal of a reversal.

Refus

  • an allocation that has already been reversed;
  • a compensating allocation, which itself cannot be reversed;
  • the mirror created by POST /v1/payments/:id/reverse : it is imposed by the payment it reverses. A disputed SEPA debit returned to the buyer leaves nothing to allocate.

The call accepts an source_reference : replay after a timeout returns the existing compensation instead of creating a second one.

Identify the reversal. Negative amounts alone are not enough to know which allocation is undone when several target the same document. The relationship is therefore explicit in both directions:

JSON
{3 items
"id":"pal_compensation"
"reverses_allocation_id":"pal_origine"
"reversed_by_allocation_id":null
}
{
"id": "pal_compensation",
"reverses_allocation_id": "pal_origine",
"reversed_by_allocation_id": null
}

reverses_allocation_id is populated on the compensation and points to the allocation being undone; reversed_by_allocation_id is populated on the original and points to its compensation. Both are null on an ordinary allocation, so a connector never needs to scan the list to determine whether an allocation was reversed.

Canceled or written-off documents. Reversing an allocation that targeted them lowers their settlement level but does not reopen never the document: reopening a written_off document would silently change the receivable based on a decision belonging to the merchant. The platform emits invoice.terminal_settlement_changed and lets a process or operator take the decision.

Events

EventTrigger
payment_allocation.partialThe allocation was created with `status=partial`: source amount is not fully allocated.
payment_allocation.completeThe allocation was created with `status=complete`: source amount is fully allocated.
invoice.paidAn invoice was fully settled through this allocation (`settlement_status` → `paid`).
invoice.partially_paidAn invoice was partially settled (`settlement_status` → `partially_paid`).
payment.matchedThe source payment (`pay_`) was fully reconciled (`status` → `matched`).

Events payment_allocation.partial and payment_allocation.complete are mutually exclusive — only one is emitted per creation. Events on target documents (invoice.paid, invoice.partially_paid, payment.matched…) are emitted in the same transaction.