Merchants, sub-merchants, terminals¶
Two extra objects inside a merchant app (
kind: "merchant"): terminals (where people pay) and sub-merchants (whose money it is). Usage and API: Pay with Gerege App.
1. Merchants¶
Your system outside Gerege App — a web shop, an app, a till, a kiosk, a vending machine. Not in the launcher, no
manifest; registered with the scopes profile.basic + payments. Review needs the legal pages (privacy, terms,
support — answering 200), a webhook URL and a live secret; then the operator checks the business, approves it and sets
its payout account. kind and return_hosts are sensitive fields — they change only in draft or after a
rejection (409 needs_review): where the person is sent after paying is something review must have seen.
2. Terminals¶
A fixed spot: a QR sticker, an NFC tag, a vending machine, a till.
- A sticker has no amount. The terminal's
url(https://geregeapp.mn/pay/t/<code>) only names the terminal. The amount comes from the open intent attached to the terminal at that moment — anybody can copy a sticker, nobody can change the amount with it. - One terminal, one open basket, per environment. A terminal has one open, unclaimed intent in live and one in test
(
409 terminal_busynames the open one). A test basket never blocks a real machine; at a terminal the app's owner and test users get the test basket first and everybody else only the live one; the public/pay/tpage shows only live. - The registry's names on the payment sheet.
labelandlocationare on the person's phone before Face ID. If someone pastes another sticker on top, the person sees the wrong machine's name and stops. codenever changes. The server issues it (10 characters).referenceis your machine's number, unique within the app (POSTagain → that terminal).- Writing takes a live key or the console. A terminal is one registry entry for both environments, so a test
key only reads (
403 live_only) — a leaked sandbox secret must not change a real machine's owner and send live money elsewhere. - A
status: "disabled"terminal's basket is not paid even by its token (409 terminal_disabled).
3. Sub-merchants¶
A platform with many owners (vending.mn — every machine owned by someone else; a kiosk hub — every service provider) makes each owner a sub-merchant inside one merchant app. The platform is the merchant of record; every owner has their own payout account and their own settlement — the rules (fee, schedule) are the app's.
code— your platform's id for the owner, immutable (400 code_immutable);POSTwith the samecode→ that row.display_nameis shown on the person's payment sheet.- A terminal with a sub-merchant makes its intents that sub-merchant's automatically.
4. Payout links — the holder approves¶
Your server cannot point an owner's takings at an account of its choosing. If it could, a compromised server would be one path to divert every owner's money at once. So:
your server ─ POST /sub-merchants/{id}/payout-link {account} (live) ─▶ Gerege
│ notification
the account's holder (a person / an organisation's admin) ◀┘
Gerege App: «{app} asks» + the terms → Face ID → approve / decline
sub-merchant.payouts_configured = true ◀─ once approved
- Who approves: the account's holder as the ledger records it — for a person's account, that person; for an organisation's account, any one of its current admins (checked again at the moment of approval).
- The terms (
terms): approving agrees that «refunds of payments made into this account (within 90 days of each payment) are taken back from this account» — with settlements off, refunds come straight out of the holder's account. - A request is valid for 7 days; states
pending | approved | declined | canceled | superseded | expired. - A sub-merchant without an approved payout gets no live intents (
409 payouts_not_configured). Test is not affected. - Requesting a payout link takes a live key (
403 live_only).
5. Patterns¶
| Merchant apps | Sub-merchants | Terminals | |
|---|---|---|---|
| A single shop | 1 | — | each till (optional) |
| A vending platform | 1 (the platform) | each machine owner | each machine |
| A kiosk hub | 1 (the hub) | each service provider | each kiosk «удахгүй» (a qr intent does not take terminal_id today) |
| A POS vendor | 1 (the vendor) | each shop | each till |
A shop being a merchant itself and granting a POS vendor the right to create keys for it (partner authorization) is «удахгүй».