Skip to content

Liquidaciones — the payout model (owner requests, operator settles)

Purpose: the one shared description of how a merchant withdraws money from the platform — who does what, how the withdrawable amount is derived, and when it refreshes. This is the product-level truth that owners, operators, and the AI agents building the surfaces all read from the same page. Audience: product, platform operators/admins, and the AI agents building the liquidaciones surfaces. Status: as of 2026-09-21 — the payout write plane is enabled in production (Liquidaciones enablement wave, PO Alfredo 2026-09-21). Source decision log: ../../backlog/ideation/archive/api-liquidaciones-operator-rollup-authz.md. Related: Card-settlement reconciliation runbook · operator-queues runbook — Liquidaciones · merchant verification — money-out-only · card-settlement model.

A merchant owner requests a withdrawal of their own comercio’s confirmed balance; a platform operator validates it and moves the money, then records the payout or rejects it. The owner never moves money and never triggers a payout — they ask, the operator disburses.

Roles — who does what (Option C, source-narrowed)

Section titled “Roles — who does what (Option C, source-narrowed)”

The payout path is owner-scoped self-serve for the request only. The two sides are deliberately split so no single actor both asks for and releases money:

  • The merchant owner submits a liquidación request for their own comercio, and views the request and its status. That is the whole of the owner’s power on this path. An owner cannot request against another merchant, cannot approve, and cannot disburse.
  • The platform operator validates and moves the money. The operator works the liquidaciones queue: they confirm the request, actually send the funds to the merchant’s bank out-of-band, and then either mark the request settled (recording the payout reference per destination) or reject it. Settle and reject are the two operator actions that resolve a request into a withdrawal or a reversal.
  • Admin ⊇ operator. A platform admin can do everything an operator can, plus the structural/dangerous escalations (verification overrides, credential management, merchant lifecycle). Any admin capability is a superset of the operator’s, never a separate parallel path.
  • The owner never triggers a payout. Submitting a request is a request, not a disbursement. The money only leaves the platform when an operator acts. This separation is the core control of the model.

Roles and the labels behind them: roles-permissions-and-labels.md. The operator’s day-to-day queue steps for liquidaciones: operator-queues runbook § Liquidaciones.

The withdrawable amount — confirmed net, not gross balance

Section titled “The withdrawable amount — confirmed net, not gross balance”

There are two different “balances,” and conflating them is the classic payout bug. The payout model withdraws only the confirmed one:

  • Gross wallet availableBalance — the snapshot a card sale credits at the moment of sale. It is immediately usable for VAS, merchant→merchant transfers, and wallet top-ups. This figure is not what a withdrawal draws against, because at sale time that card money is still virtual (promised by the payment processor, not yet confirmed as deposited to the platform).
  • Withdrawable amount = settlement_reports.availableAmount — the confirmed net from card settlement: the gross of confirmed sales, T+1, net of the platform operator’s effective-dated commission. This is the figure a liquidación may draw down. A withdrawal is gated on this confirmed number, never on the gross snapshot.

So “how much can I withdraw” and “how much can I spend on VAS/transfers/top-ups” are answered by two distinct figures on purpose: settlement gates money-out to a bank; it does not touch the immediately-usable in-platform balance. The full derivation of the confirmed net (the three separate money figures, the effective-dated commission, and how confirmation is imported) lives in the CardSettlement decision log — ../../backlog/ideation/api-card-settlement-angelpay-reconciliation.md — and its domain page, card-settlement model.

Refresh semantics — the source updates the report, not a trigger

Section titled “Refresh semantics — the source updates the report, not a trigger”

The withdrawable report refreshes when its source produces new confirmed data, not when anyone presses a button. The source is a realm setting, settlement.source, whose default is angelpay_import (the payment processor’s settlement import):

  • The report updates when the operator imports the processor’s export. Confirmed settlement enters the system only through that import; that is what advances settlement_reports.availableAmount. There is no owner-side action that produces new confirmed money.
  • The owner’s “actualizar” re-reads the latest report. When an owner refreshes, they re-fetch the most recent settlement report and see its asOf timestamp — they are looking at the freshest confirmed figure, not causing a recomputation. There is no owner-triggered rollup.
  • The on-demand rollup endpoint is an operator/support tool for the fallback source only. The POST /pos/settlements/ops/rollup trigger stays operator/admin-only and applies only when settlement.source = computed_rollup — the fallback that computes reports from the platform’s own records for a future processor that cannot provide a settlement export. It is not part of the normal owner path.

This supersedes the earlier A/B/C/D rollup-trigger question in the ideation log (../../backlog/ideation/archive/api-liquidaciones-operator-rollup-authz.md): the resolved model is that the source (an import), not a trigger, drives the report. The owner “requests” and “views”; nobody but the source advances the confirmed number. The kill-switch semantics for settlement.source and the on-demand fallback are in the card-settlement reconciliation runbook; realm-setting resolution is in runtime-settings.md.

The money-out gate — verified merchant + verified bank account

Section titled “The money-out gate — verified merchant + verified bank account”

A withdrawal is money leaving the platform, so it sits behind the money-out gate:

  • A liquidación requires a verified merchant (owner KYC approved) and a verified bank account (a verified CLABE is the payout destination, so its verification is intrinsic to the gate). If either is missing, the request is default-deny and the owner is directed to complete verification.
  • Money-OUT always needs verification. Liquidaciones, merchant→merchant transfers and wallet→platform top-ups require a verified merchant in every policy. Under the default policy B an unverified merchant also cannot sell, open shifts, move cash or invite staff (it can set up: catalog, appearance, 1 store, 1 terminal); a platform admin can flip the realm switch merchant.unverifiedCanOperate to policy A, where selling is open from day one and only money-out waits.
  • allowUnverifiedSales is retired — it is neither a column to read nor an override to set. It is superseded by attestation (a platform admin can verify checks on a merchant’s behalf, including confirming its registered bank account) plus suspension as the single audited kill-switch. The authoritative rule and its capability table: merchant verification policy.
  1. Owner requests. From the merchant surface the owner submits a liquidación request against their own comercio’s withdrawable amount, choosing a verified bank-account destination.
  2. The money is reserved. Submitting the request reserves the amount — it is debited from the withdrawable figure and the request lands in progress. The reservation is what keeps the money from being requested twice.
  3. Operator validates and disburses. The operator works the request in the liquidaciones queue, sends the funds to the destination out-of-band, and marks it settled — recording the payout reference for each destination as the merchant’s proof.
  4. Or the operator rejects. If the request cannot be paid, the operator rejects it with a curated reason; a compensating credit restores the reserved amount so the money is never stranded, and the owner sees the reason.

The operator-side mechanics (curated rejection reasons, capturing the reference per destination, auditing) are in the operator-queues runbook § Liquidaciones.

What this page deliberately does not promise

Section titled “What this page deliberately does not promise”
  • No timeframe. This page states no turnaround or duration for a payout. The disbursement is completed by a person on the platform team; until there is a committed queue-watch cadence that makes an interval true, stating one would be a promise the operation does not guarantee. The mechanism — reserve on request, operator disburses, notify on completion — is what is true; a duration is not.
  • No vendor or brand names. This page names mechanisms only — “the payment processor” / “procesador de pagos”, “the platform”, “the platform operator”. Owner- and operator-facing copy never carries the processor’s brand; brand names live in code, column mappings, and internal decision logs, never on this shared model page or in examples.