Preview — pending review
This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.
Declare a bank transfer against an outstanding ledger entry
Executes the "Pay now" flow: the tenant DECLARES that it has wired the money for an outstanding
ledger entry to the published payee account (see GET .../billing/payment-instructions). The
entry moves to pending-manual-approval and, when receiptFileName is supplied, gains a
placeholder awaiting-review SWIFT/EFT receipt. A charge (an invoice charge or a commitment
upfront — a debt) keeps its type; a payment row becomes wire-transfer-pending. A declared
debt cannot be cancelled by the tenant (…/actions/cancel answers 409).
This action settles nothing. No invoice is flipped PAID, no wallet grant is credited, no
commitment is activated and no ledger entry is marked completed. The platform stores no cards
and runs no payment processor, so there is no instant settlement to offer: a platform Finance
operator verifies the transfer arrived against the bank feed (SLA: 1 business day) and settles
it exactly once through the operator confirm action — or resolves it with the operator reject
action. Settlement is the operator's, never the payer's.
Validation: the addressed transaction must exist in the scope (else NOT_FOUND); an
already-completed entry is CONFLICT; method must be wire — method=card is REFUSED with
CONFLICT (it is retired PSP-era surface that used to settle self-service); a settling
credit-applied or refund movement is not payable (CONFLICT) — the customer never wires
those; caller needs contributor/admin/owner or billing role, otherwise FORBIDDEN. Guards are
evaluated before any mutation, so a refusal leaves the ledger entry and its linked invoice
unchanged.
Async & state: Asynchronous — 202 returning the transaction in pending-manual-approval
(type unchanged for a charge, wire-transfer-pending otherwise); terminal states completed (operator-confirmed
against the bank feed) or failed (operator-rejected / tenant-cancelled), emitted as
resource.updated SSE frames with kind billing.transaction patching status and the receipt
verification field.
Errors: 401 unauthenticated; 403 insufficient role; 404 unknown scope/transaction; 409
CONFLICT entry already settled, entry type not payable, or method=card; 422 invalid method;
429 repeated payment attempts rate-limited; 500 ledger failure.
Idempotency/Concurrency: This operation does not use Idempotency-Key; it may be omitted
and a sent one is ignored. The entry is locked FOR UPDATE so concurrent declarations serialize;
re-declaring an entry already in pending-manual-approval replaces its placeholder receipt
rather than posting a second entry.
bearerTokenAuthorizationBearer <token>An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.
scopeId*stringOpaque ownership+authorization scope resolving to tenant + subscription + project.
transactionId*stringTransaction ledger entry identifier the payment action is anchored to.
application/json- body
Input for the "Pay now" flow — declare that a bank transfer was sent for an outstanding ledger entry, which a platform operator then reconciles. Settles nothing on its own.
invoiceId?stringDeprecatedDeprecated, optional and IGNORED — the entry settled is always the addressed transactionId, and the linked invoice (if any) is taken from that entry, never from this field. Omit it.
method*stringMust be wire: the entry becomes wire-transfer-pending / pending-manual-approval and waits for an operator to confirm the money arrived. card is REFUSED with CONFLICT — the platform stores no cards and runs no PSP, and a payer may not settle its own entry.
"card""wire"receiptFileName?|Name of the uploaded SWIFT/EFT receipt file; a placeholder receipt is recorded when given.
Deprecated success shape from the retired instant-settlement (card) path; no longer returned — a declared bank transfer answers 202.
application/json- response
One entry in the billing transaction ledger. amount is in ten-thousandths of the currency unit, signed by effect on the outstanding balance: charges positive (you owe more), payments / credits / refunds negative.
id*stringLedger entry identifier (e.g. tx-9f31ad).
type*TransactionTypeTransaction ledger entry kind.
"charge""payment""credit-applied""refund""wire-transfer-pending"description*stringHuman-readable ledger description (e.g. "Card payment — Visa •••• 4242").
amount*integerSigned amount in ten-thousandths of the currency unit; charges positive, payments/credits/refunds negative.
method*stringPayment method label (e.g. "Visa •••• 4242", "Wire transfer — Barclays", "Invoice", "Credit balance").
status*TransactionStatusTransaction settlement status.
"completed""pending""pending-manual-approval""failed"invoiceId*|Linked invoice id, or null for account-level entries.
invoiceNumber*|Linked invoice number (e.g. STC-2026-1039), or null.
reference*stringProcessor/ledger reference (prefixed ch_, pay_, cr_, re_, wt_).
createdAt*stringdate-timefailureReason*|Processor decline reason for failed entries (e.g. "Issuer declined — insufficient funds (code 51)"); null otherwise.
commitmentId*|The commitment whose upfront this charge pays, activated when the entry settles; null for every other entry, including a plain invoice charge. Present-as-null on purpose: an operator may confirm (or reject) a charge ONLY when it carries a commitment, so this is the field that tells a confirmable upfront apart from an invoice charge, for which those actions are always a conflict.
curl -X POST "https://example.com/scopes/string/billing/transactions/string/actions/pay" \ -H "Content-Type: application/json" \ -d '{ "method": "card" }'{ "id": "string", "type": "charge", "description": "string", "amount": 0, "method": "string", "status": "completed", "invoiceId": "string", "invoiceNumber": "string", "reference": "string", "createdAt": "2019-08-24T14:15:22Z", "failureReason": "string", "commitmentId": "string"}