A mini app inside Gerege App¶
What you will do: turn your web app into a mini app that opens inside Gerege App, get the person's sign-in (launch → token), and ask for a payment through the bridge. Time: about 30 minutes (if your web app is already on https). What you need: §0–§2 of the Quickstart (an organisation, «Mini апп-ууд», a console session), an https origin, a backend.
A mini app is your web app, listed in Gerege App's launcher and opened inside the app (WKWebView). How it differs from
a merchant: Merchants and mini apps. The standard is Gerege's implementation of OMAS 1.0 — a
backend written for OMAS works by changing its values only.
1. Register¶
curl -sS "$GEREGE/dev/apps" -H "Authorization: Bearer $GEREGE_SESSION" -H 'Content-Type: application/json' \
-d '{"slug": "my-esim", "name": "My eSIM", "entry_url": "https://esim.example.mn/app",
"category": "travel", "developer_name": "Example LLC"}' | tee app.json | jq '{id, slug, test_client_id, live_client_id, verification_token}'
export APP_ID=$(jq -r .id app.json)
The console's (/apps/miniapp) register sheet does the same. Registering issues mapp_… (live) and mapp_test_…
(test) client ids and an omas-verify=… token. The app is a draft; its scope is profile.basic — to take payments,
add payments with a PATCH (while it is a draft).
2. Publish and check the manifest¶
Publish /.well-known/gerege-miniapp.json on your origin (every field: Manifest):
{
"omas_version": "1.0",
"slug": "my-esim",
"client_id": "mapp_…",
"version": "1.0.0",
"name": { "mn": "Миний eSIM", "en": "My eSIM" },
"entry": "https://esim.example.mn/app",
"origins": ["https://esim.example.mn"],
"icons": [{ "src": "https://esim.example.mn/icon-512.png", "size": 512 }],
"scopes": ["profile.basic", "payments"],
"bridge": { "min_version": 1, "methods": ["getContext", "getLaunchCode", "requestPayment", "close"] },
"legal": { "privacy_url": "https://example.mn/privacy", "terms_url": "https://example.mn/terms", "support_url": "https://example.mn/help" },
"verification": "omas-verify=…"
}
curl -sS -X POST "$GEREGE/dev/apps/$APP_ID/manifest/check" -H "Authorization: Bearer $GEREGE_SESSION" | jq
The check proves the origin is yours (verification) and probes a 512×512 PNG icon and the three legal pages
(answering 200). Before you deploy, POST /dev/manifest/validate checks a manifest sent as the body.
3. Test credentials and test users¶
curl -sS "$GEREGE/dev/apps/$APP_ID/keys" -H "Authorization: Bearer $GEREGE_SESSION" \
-H 'Content-Type: application/json' -d '{"name": "backend", "environment": "test", "preset": "miniapp_backend"}' \
| jq '{client_id, client_secret, scopes}'
The «Mini app backend» preset = oauth:token, payments:read, payments:write, refunds:write.
A draft app is seen and opened in Gerege App's launcher by the person who registered it and its test users
(active members of your organisation, ≤ 50); their launch codes are redeemed with the test credential and no money
moves. Add a test user: POST /dev/apps/{id}/test-users {"email"} (Developer sandbox).
4. Launch → token¶
Gerege App opens the app at entry?launch=<code>. The frontend reads launch from the URL, removes it from history
and sends it to your backend; the backend exchanges the single-use code for tokens:
curl -sS "$GEREGE/oauth/token" -u "$GEREGE_CLIENT_ID:$GEREGE_CLIENT_SECRET" \
-d grant_type=authorization_code -d code=gml_…
{ "token_type": "Bearer", "access_token": "gma_at_…", "expires_in": 1800, "refresh_token": "gma_rt_…",
"scope": "profile.basic payments",
"user": { "ref": "u_9f2c…", "sub": "u_9f2c…", "verified": true, "locale": "mn" } }
The code lives 60 seconds and works once; sub is a pseudonymous id that is stable for your app. Details
(refresh rotation, /me, consent, requires_verified/min_age): Mini app launch and tokens.
5. Ask for a payment¶
The backend creates the intent with the person's token (presentment: "app" — the default) and the frontend opens the
payment sheet through the bridge:
curl -sS "$GEREGE/payment-intents" -H "Authorization: Bearer gma_at_…" \
-H 'Content-Type: application/json' -H 'Idempotency-Key: order-77' \
-d '{"amount": 45000, "description": "eSIM 7 days", "reference": "order-77"}' | jq '{id, status}'
const res = await window.gerege.requestPayment({ intentId: "pi_…" });
// res.status: "succeeded" | "canceled" | "failed" — DO NOT TRUST IT: verify on the backend with GET or the webhook
The whole payments API, manual capture, refunds: Mini app payments. Every bridge
method: Bridge. Webhooks: Webhooks (required for an app with
the payments scope).
6. Review and publishing¶
POST /dev/apps/{id}/submit — needs a checked manifest, privacy/terms/support links, a live secret and (with
payments) a webhook URL; during review the app is frozen. Once approved it is listed for everyone; where it
appears on the launcher's home screen is the operator's layout. The full list:
Review requirements. The states (draft → in_review → approved | rejected,
suspended): Test and live.