Skip to content

Objects

Use this page to look up every field, type and meaning of the objects that API answers and webhooks' data.object carry. It is a reference — keep it open beside your code.

The payment intent has its own page: Payment intent. The rest are here.

Common rules (API conventions):

  • Money is whole ₮ (integer); the currency is always MNT.
  • Times are RFC 3339 in UTC (2026-10-22T09:00:00Z).
  • A field marked «nullable» is always present and may be null; every other field is never null.
  • Minor versions may add fields — ignore the ones you do not know.

Refund

The answer of POST /payment-intents/{id}/refunds, and data.object of refund.succeeded / refund.failed. Explained in Refunds.

Field Type nullable Meaning
id string re_ + 24 base62
object string "refund"
intent_id string the refunded intent (pi_…)
amount integer the amount refunded, ₮
status string pending · succeeded · failed
reason string the reason you gave (≤ 255), or "". Never shown in the person's notification
failure_code string yes when failed: insufficient_funds · settlement_shortfall · refund_rejected (Error codes)
livemode boolean whether it is live
created_at string (time)
{
  "id": "re_2kLm9Pq4Rs6Tu8Vw0Xy1Za3B",
  "object": "refund",
  "intent_id": "pi_4fQ2mX8kLp0aZr7TbN3cVw9E",
  "amount": 10000,
  "status": "succeeded",
  "reason": "supplier_failed",
  "failure_code": null,
  "livemode": true,
  "created_at": "2026-10-22T09:00:00Z"
}

Settlement

GET /settlements (items[]), GET /settlements/{id}, and data.object of settlement.paid. Live only. Explained in Settlements.

Field Type nullable Meaning
id string st_ + 24 base62
object string "settlement"
status string pending · paid · failed
cutoff string (time) the payments captured before this instant are in it
gross integer the payments' total
refunds integer the refunds deducted
reserve_refunds · holdback · released integer always 0 (this platform keeps no reserve or holdback; OMAS compatibility fields)
fee integer the fee this settlement actually took; negative when it returned more than it took
net integer gross − refunds − fee
recovered integer earlier refunds that exceeded a settlement, deducted now (clearing_carried_in − clearing_carried_out; negative = carried on to the next one)
paid integer what went to the payout account (may be 0)
intent_count · refund_count integer the number of payments and refunds in it
destination_masked string yes the payout account, last 4 digits (******0042)
holdback_release_at string (time) yes always null
livemode boolean true
created_at string (time)
paid_at string (time) yes when it became paid
fee_assessed integer the fee assessed on the payments
fee_returned integer fee given back with refunds (when the rule has refund_fee)
fee_carried_in · fee_carried_out integer fee brought in from the previous / carried to the next settlement
clearing_carried_in · clearing_carried_out integer refund excess brought in from the previous / carried to the next settlement
failure_code string yes when failed (Error codes)
sub_merchant string (UUID) yes the sub-merchant's id for a sub-merchant's settlement; null for the app's own

Identities: net = gross − refunds − fee, paid = net − holdback + released − reserve_refunds − recovered.

{
  "id": "st_7QwErTy2UiOp4AsDf6GhJk8L",
  "object": "settlement",
  "status": "paid",
  "cutoff": "2026-10-21T16:00:00Z",
  "gross": 100000,
  "refunds": 5000,
  "reserve_refunds": 0,
  "fee": 2000,
  "net": 93000,
  "holdback": 0,
  "released": 0,
  "recovered": 0,
  "paid": 93000,
  "intent_count": 3,
  "destination_masked": "******0042",
  "holdback_release_at": null,
  "livemode": true,
  "created_at": "2026-10-22T08:58:00Z",
  "paid_at": "2026-10-22T08:59:00Z",
  "refund_count": 1,
  "fee_assessed": 2000,
  "fee_returned": 0,
  "fee_carried_in": 0,
  "fee_carried_out": 0,
  "clearing_carried_in": 0,
  "clearing_carried_out": 0,
  "failure_code": null,
  "sub_merchant": null
}

GET /settlements/{id} adds to those fields intents[] (id, amount, fee, reference (nullable), confirmed_at (nullable)), refund_items[] (id, intent_id, amount, fee_returned, source) and truncated — with more than 1000 lines, truncated: true and only the first 1000 come.

{
  "id": "st_7QwErTy2UiOp4AsDf6GhJk8L",
  "object": "settlement",
  "status": "paid",
  "…": "…",
  "intents": [
    { "id": "pi_4fQ2mX8kLp0aZr7TbN3cVw9E", "amount": 65000, "fee": 1300, "reference": "order_8812", "confirmed_at": "2026-10-21T03:12:00Z" }
  ],
  "refund_items": [
    { "id": "re_2kLm9Pq4Rs6Tu8Vw0Xy1Za3B", "intent_id": "pi_4fQ2mX8kLp0aZr7TbN3cVw9E", "amount": 5000, "fee_returned": 0, "source": "clearing" }
  ],
  "truncated": false
}

Terminal

The answers of /terminals… (a list is {"data": [Terminal]}). Explained in Pay with Gerege App.

Field Type nullable Meaning
id string (UUID) an intent's terminal_id
object string "terminal"
code string 10 characters the server assigns (23456789abcdefghjkmnpqrstuvwxyz); never changes
url string what goes on the sticker's QR and the NFC tag: https://geregeapp.mn/pay/t/<code> — carries no amount
label string 1–60, shown on the payment sheet before Face ID
location string ≤ 120, or ""
reference string yes your number (^[A-Za-z0-9_.:-]{1,64}$), unique within the app
sub_merchant string (UUID) yes the terminal's sub-merchant
status string active · disabled
created_at · updated_at string (time)
{
  "id": "4b8e6c1a-2d3f-4a5b-9c7d-0e1f2a3b4c5d",
  "object": "terminal",
  "code": "7k2m9x4q3p",
  "url": "https://geregeapp.mn/pay/t/7k2m9x4q3p",
  "label": "Машин №7",
  "location": "СБД, 1-р хороо",
  "reference": "vm-7",
  "sub_merchant": "9a7c5e3b-1d2f-4e6a-8b0c-7d9e1f3a5b7c",
  "status": "active",
  "created_at": "2026-10-22T08:00:00Z",
  "updated_at": "2026-10-22T08:00:00Z"
}

SubMerchant

The answers of /sub-merchants… (a list is {"data": [SubMerchant]}).

Field Type nullable Meaning
id string (UUID) an intent's sub_merchant_id
object string "sub_merchant"
code string its id on your platform (^[A-Za-z0-9_.:-]{1,40}$); never changes
display_name string 1–80, shown to the person paying
legal_name string ≤ 160, or ""
reg_no string ≤ 20, or ""
status string active · disabled
payouts_configured boolean whether its holder approved a payout account — when false, a live payment is payouts_not_configured
payout_account string yes the approved account, last 4 digits (******3456)
payout_linked_at string (time) yes when it was approved
created_at · updated_at string (time)
{
  "id": "9a7c5e3b-1d2f-4e6a-8b0c-7d9e1f3a5b7c",
  "object": "sub_merchant",
  "code": "owner-17",
  "display_name": "Батаа ХХК",
  "legal_name": "Батаа ХХК",
  "reg_no": "6543210",
  "status": "active",
  "payouts_configured": true,
  "payout_account": "******3456",
  "payout_linked_at": "2026-10-22T08:30:00Z",
  "created_at": "2026-10-22T08:00:00Z",
  "updated_at": "2026-10-22T08:30:00Z"
}

The answer of POST /sub-merchants/{sid}/payout-link, and GET …/payout-links ({"data": [PayoutLink]}, newest first, ≤ 50). Explained in Payout accounts.

Field Type nullable Meaning
id string (UUID)
object string "payout_link"
sub_merchant string (UUID)
status string pending · approved · declined · canceled (replaced by a newer request) · superseded (replaced by a later approved link) · expired (unanswered for 7 days)
account_masked string the account asked for, last 4 digits
requested_at string (time)
expires_at string (time) requested_at + 7 days
decided_at string (time) yes when it was approved / declined
terms object {"mn", "en"} — what the holder agrees to by approving (below)

terms (both languages, always the same): «Энэ данс руу орсон төлбөрүүдийн буцаалтыг (төлбөрөөс хойш 90 хоногийн дотор) энэ данснаас хасна.» / «Refunds of payments made into this account (within 90 days of each payment) are taken back from this account.»

{
  "id": "5d1f0a2b-3c4d-4e5f-8a6b-7c8d9e0f1a2b",
  "object": "payout_link",
  "sub_merchant": "9a7c5e3b-1d2f-4e6a-8b0c-7d9e1f3a5b7c",
  "status": "pending",
  "account_masked": "****************2345",
  "requested_at": "2026-10-22T08:10:00Z",
  "expires_at": "2026-10-29T08:10:00Z",
  "decided_at": null,
  "terms": {
    "mn": "Энэ данс руу орсон төлбөрүүдийн буцаалтыг (төлбөрөөс хойш 90 хоногийн дотор) энэ данснаас хасна.",
    "en": "Refunds of payments made into this account (within 90 days of each payment) are taken back from this account."
  }
}

Event

The body of every webhook, and the answer of GET /events · GET /events/{id} — the very same bytes (the stored, signed body). The type of data.object follows type — Event reference, Events API.

Field Type nullable Meaning
id string evt_ + 24 base62 — dedupe on it (the same as the Gerege-Event-Id header)
type string payment_intent.succeeded etc.
created_at string (time) when the event was made, to the second
livemode boolean
app string the app's slug
data.object object a PaymentIntent, Refund, Settlement, AppStatus, Consent or WebhookTest
{
  "id": "evt_Vec0000000000000000000003",
  "type": "refund.succeeded",
  "created_at": "2026-10-22T09:00:00Z",
  "livemode": true,
  "app": "esim",
  "data": { "object": { "id": "re_2kLm9Pq4Rs6Tu8Vw0Xy1Za3B", "object": "refund", "…": "…" } }
}

AppStatus

data.object of app.status_changed: the app's status or review_status changed.

Field Type nullable Meaning
object string "app"
slug string
status · previous_status string draft · active · maintenance · disabled
review_status · previous_review_status string draft · in_review · approved · rejected · suspended
review_note string yes the operator's note on a rejection or suspension
{
  "object": "app",
  "slug": "esim",
  "status": "active",
  "review_status": "suspended",
  "previous_status": "active",
  "previous_review_status": "approved",
  "review_note": "Хэрэглэгчийн гомдол шалгагдаж байна"
}

data.object of consent.revoked: the person disconnected the app; every token for them is already revoked.

Field Type nullable Meaning
object string "consent"
user_ref string that person's pairwise name (sub / ref)
revoked_at string (time)
{ "object": "consent", "revoked_at": "2026-10-22T09:00:00Z", "user_ref": "u_78a08c3afb344c1b4b765aead45e1693" }

WebhookTest

data.object of webhook.test (the console's test send; livemode is always false).

Field Type nullable Meaning
object string "webhook_test"
message string "Gerege App webhook test"
{ "message": "Gerege App webhook test", "object": "webhook_test" }

Public /pay views

GET /api/v1/miniapp/pay/{token} and GET /api/v1/miniapp/pay/t/{code} — no authentication; the /pay/… page on a computer reads them. No personal data: no description, reference, metadata, nor who claimed it.

Field (payment) Type nullable Meaning
object string "payment"
merchant object {name, icon_url} — the app's approved name and icon
terminal object yes {code, label, location}
amount · currency integer · string
status string the intent's status
claimed boolean whether somebody claimed it («confirm on your phone»)
expires_at string (time)
livemode boolean
{
  "object": "payment",
  "merchant": { "name": "Vending.mn", "icon_url": "https://vending.mn/icon-512.png" },
  "terminal": { "code": "7k2m9x4q3p", "label": "Машин №7", "location": "СБД, 1-р хороо" },
  "amount": 3500,
  "currency": "MNT",
  "status": "requires_confirmation",
  "claimed": false,
  "expires_at": "2026-10-22T09:05:00Z",
  "livemode": true
}

/pay/t/{code} is {"object": "terminal", "merchant", "terminal", "pending"} — pending is the terminal's open, unclaimed live intent (the payment object above) or null. An unknown or disabled terminal, or a suspended merchant → 404.

{
  "object": "terminal",
  "merchant": { "name": "Vending.mn", "icon_url": "https://vending.mn/icon-512.png" },
  "terminal": { "code": "7k2m9x4q3p", "label": "Машин №7", "location": "СБД, 1-р хороо" },
  "pending": null
}

Token and /me

POST /oauth/token → {token_type: "Bearer", access_token, expires_in, refresh_token, scope, user: {ref, sub, verified, locale}}; GET /me → {ref, sub, verified, locale, scope, environment} plus, when granted, email (profile.email) and phone (profile.phone, E.164). ref and sub are the same pairwise value. More: Mini app launch & tokens.

{
  "token_type": "Bearer",
  "access_token": "gma_at_…",
  "expires_in": 1800,
  "refresh_token": "gma_rt_…",
  "scope": "profile.basic payments",
  "user": { "ref": "u_9f2c4e7a1b3d5f60718293a4b5c6d7e8", "sub": "u_9f2c4e7a1b3d5f60718293a4b5c6d7e8", "verified": true, "locale": "mn" }
}

WebhookEndpoint

The answer of /webhook-endpoints… (a live key, webhooks:write) and of the console's /dev/apps/{id}/webhook-endpoints…. A list is {"data": [WebhookEndpoint], "next_cursor": null}; creating (201) and rotating the secret (200) answer {"endpoint": WebhookEndpoint, "webhook_secret": "whsec_…", "notice": "…"} — the secret is in that answer only. More: Webhooks.

Field Type nullable Meaning
id string we_ + 24 base62
object string "webhook_endpoint"
environment · livemode string · boolean test / live — an endpoint receives its own environment's events only
url string https, a public address
description string ≤ 200, or ""
event_types string[] the filter, ≤ 20; [] = every event (webhook.test is not filterable — a test always arrives)
status string active · disabled (you turned it off) · auto_disabled (every delivery failed for 5 days)
disabled_reason string yes why, when auto_disabled
legacy boolean true = endpoint №1 — moved from the app's old single webhook URL (the console's POST /dev/apps/{id}/webhook edits it)
previous_secret_until string (time) yes after a rotation, until when the previous secret still co-signs (24 hours)
failing_since string (time) yes when every delivery started failing; a successful one clears it
last_success_at string (time) yes the last successful delivery
deliveries_24h object (lists only) {delivered, failing} — deliveries of the last 24 hours
created_at · updated_at string (time)
{
  "id": "we_8kQ2mX4pL7zR1tV9bN3cW5yA",
  "object": "webhook_endpoint",
  "environment": "live",
  "livemode": true,
  "url": "https://shop.mn/hooks/gerege",
  "description": "Order server",
  "event_types": ["payment_intent.succeeded", "refund.succeeded", "refund.failed"],
  "status": "active",
  "disabled_reason": null,
  "legacy": false,
  "previous_secret_until": null,
  "failing_since": null,
  "last_success_at": "2026-10-27T03:12:09Z",
  "created_at": "2026-10-20T08:00:00Z",
  "updated_at": "2026-10-20T08:00:00Z"
}

TerminalBatch

The answer (200) of POST /terminals/batch — each row's outcome, in the order sent. When any row is wrong (400 validation_error, terminals[i].…) the whole batch is refused and this object does not come.

Field Type nullable Meaning
object string "terminal_batch"
data[].index integer the row's position (from 0)
data[].status string created · existing (that reference is registered — retrying is safe) · failed · skipped (not attempted — send the batch again)
data[].terminal Terminal yes for created / existing
data[].error object (failed only) {code, error} — reference_taken, invalid_sub_merchant, …
created · existing · failed · skipped integer counts
{
  "object": "terminal_batch",
  "data": [
    { "index": 0, "status": "created", "terminal": { "id": "4b8e6c1a-2d3f-4a5b-9c7d-0e1f2a3b4c5d", "object": "terminal", "code": "7k2m9x4q3p", "…": "…" } },
    { "index": 1, "status": "failed", "terminal": null, "error": { "code": "invalid_sub_merchant", "error": "…" } }
  ],
  "created": 1, "existing": 0, "failed": 1, "skipped": 0
}

Statement

GET /statements?from=&to=&sub_merchant_id=&format=json|csv (settlements:read) — the app's money movements, one row each, by Ulaanbaatar day. With format=csv the same rows as CSV (UTF-8 BOM, ,, header: date, type, payment_intent, refund, settlement, sub_merchant, reference, gross, fee, net, balance_after, currency). More: Statements.

Field Type nullable Meaning
object string "statement"
app_id string (UUID)
sub_merchant string (UUID) yes that stream when sub_merchant_id was given ("" = the app's own — null)
environment string the key's environment
from · to string YYYY-MM-DD (both included), timezone: Asia/Ulaanbaatar
currency string MNT
streams[] object each stream (the app's own, each sub-merchant's): {sub_merchant, opening_balance, closing_balance}
totals object {captured, refunded, fees, settlement_paid, net}
data[].date · data[].at string the Ulaanbaatar date · the UTC instant
data[].type string captured · refunded · fee · settlement_paid · fee_carried · clearing_carried
data[].payment_intent · refund · settlement · sub_merchant · reference string yes the row's objects
data[].gross · fee · net integer the row's amounts (₮, signed)
data[].balance_after integer the stream's clearing balance after the row
data[].currency string MNT

A statement is ≤ 100 000 rows (422 statement_too_large — shorten the range). In a stream without settlements (most apps today, and test mode) every capture went straight to the payout account, so each captured row is followed by a settlement_paid row of the same amount and the balance stays 0.

Key

The console's «Keys» (/dev/apps/{id}/keys…) — not a server API: only the console creates and shows keys. Creating and rolling also answer client_secret (once), notice, and on a roll previous_key. Rules: API conventions.

Field Type nullable Meaning
id string (UUID) the console's id
object string "api_key"
name · environment string ≤ 60 · test / live
client_id string gk_live_… / gk_test_… (mapp_… for the old pair)
secret_hint string yes the secret's last 4 characters
scopes string[] payments:read, …
allowed_ips string[] CIDRs; [] = anywhere
legacy boolean the «default key» (the old mapp_… pair)
status string active · expired · revoked
created_by object yes {user_id, name}
created_at · expires_at · last_used_at · revoked_at string (time) all but created_at last_used_at is updated at most once a minute
last_used_ip · revoke_reason · rolled_from · rolled_to string yes