Танилцуулга / API
API лавлагаа
PayGrid REST API нь Berlin Group NextGenPSD2 v2.x verbatim adoption дээр PayGrid-ийн нэмэлт endpoint-уудыг (alias DICT, PSP onboarding, QR Switch) орохуулсан. Бүх POST endpoint idempotency-key-аар replay-protected; бүх authentication mTLS + ES256 JWT-аар.
1. Base URL ба versioning
Production: https://api.paygrid.mn/v1/
Sandbox: https://sandbox.paygrid.mn/v1/
Versioning: URI path-аар (/v1/, /v2/ in future)
Stable for ≥ 2 жил per major version
Deprecation notice ≥ 6 сар before removal
2. Authentication
Бүх хүсэлтэд гурван давхрага.
mTLS
- TLS 1.3 only
- Client cert pinned-аар PSP / Bank participant-аар тус тусдаа
- nginx termination · pass-through cert subject + verification result via headers
X-SSL-Client-Verify,X-SSL-Client-S-DN,X-SSL-Client-Fingerprint - Cert chain: PayGrid internal CA + Mongolian Trust Service CAs
- Validity ≤ 1 жил; OCSP + CRL revocation
JWT (per-request)
Algorithm: ES256 (preferred) or RS256
HS256 forbidden
Claims:
iss = participant BIC (e.g., KHANUBXX)
aud = api.paygrid.mn
iat = current unix
exp = ≤ iat + 60s
jti = unique per request
Public key: pinned per participant-аар DB-д хадгалагдсан
Header-үүд
Authorization: Bearer <JWT>
X-Request-ID: UUID (per-request)
X-Idempotency-Key: UUID (per logical operation)
X-Participant-BIC: requesting participant BIC
PSU-IP-Address: end-user IP (FRM-аар)
PSU-User-Agent: end-user User-Agent
3. Endpoint inventory
Bank-facing (NextGenPSD2 verbatim)
POST /v1/payments/sepa-credit-transfers Initiate payment
GET /v1/payments/sepa-credit-transfers/{id} Get payment
GET /v1/payments/sepa-credit-transfers/{id}/status Get status
PUT /v1/payments/sepa-credit-transfers/{id}/cancellation-authorisations
PSP-facing (PayGrid extensions)
POST /v1/aliases Register merchant alias
GET /v1/aliases/{alias} Resolve alias
DELETE /v1/aliases/{alias} Revoke alias
POST /v1/aliases/{alias}/verify Confirmation of Payee
POST /v1/psp/onboard PSP self-onboarding (sandbox)
PUT /v1/psp/{bic}/keys Rotate signing keys
GET /v1/psp/{bic}/balance Nostro position
POST /v1/psp/{bic}/webhooks Configure webhooks
QR Switch
POST /v1/qr/resolve Parse + resolve EMVCo TLV
POST /v1/qr/static/create Generate static MPQR
POST /v1/qr/dynamic/create Generate dynamic MPQR (POS)
POST /v1/qr/cpqr/generate Generate CPQR (consumer)
GET /v1/qr/{qr_id}/status QR status
DELETE /v1/qr/{qr_id} Cancel/revoke QR
Settlement / audit / health
GET /v1/settlement/positions Per-PSP nostro
POST /v1/settlement/eod Trigger EOD batch
GET /v1/settlement/batches/{date} Retrieve batch report
GET /v1/audit/payments Query payments (signed link)
POST /v1/audit/export Generate audit export
GET /v1/health/live Liveness
GET /v1/health/ready Readiness
GET /v1/health/dependencies DB + Redis + HSM status
4. POST /v1/payments/sepa-credit-transfers
Зорилго: Хэтэвч PSP хэрэглэгчийн банкны данснаас beneficiary-руу төлбөр эхлүүлэх.
Request
POST /v1/payments/sepa-credit-transfers HTTP/1.1
Host: api.paygrid.mn
Authorization: Bearer <JWT>
Content-Type: application/json
X-Request-ID: 550e8400-e29b-41d4-a716-446655440000
X-Idempotency-Key: GW-INTENT-xyz789
X-Participant-BIC: GWMNUBXX
PSU-IP-Address: 203.0.113.42
PSU-User-Agent: GeregeWallet/1.0 iOS/17.5
TPP-Redirect-URI: https://api.wallet.gerege.mn/payment/done/xyz789
{
"instructedAmount": {
"currency": "MNT",
"amount": "100000.00"
},
"debtorAccount": {
"iban": "MN10080010100012345678"
},
"creditorAccount": {
"iban": "MN20910010000000XXXX"
},
"creditorName": "Gerege Wallet — Bat Erdene",
"remittanceInformationUnstructured": "Wallet top-up",
"endToEndIdentification": "GW-INTENT-xyz789",
"binding_jws": "<JWS containing Dynamic Linking payload>"
}
Response (201 Created)
{
"transactionStatus": "RCVD",
"paymentId": "p_paygrid_550e8400...",
"_links": {
"scaRedirect": {
"href": "https://khanbank.mn/sca/p_khan_abc123?return=..."
},
"self": { "href": "/v1/payments/sepa-credit-transfers/p_paygrid_550e8400..." },
"status": { "href": "/v1/payments/sepa-credit-transfers/p_paygrid_550e8400.../status" }
},
"_paygrid": {
"frm_score": 0.12,
"frm_action": "PASS",
"debtor_kyc_level": "QUALIFIED",
"creditor_kyc_level": "BASIC",
"high_risk_combination": false
}
}
Possible transactionStatus values
RCVD | Received |
PDNG | Pending |
ACTC | AcceptedTechnicalValidation |
ACFC | AcceptedFundsChecked |
ACSP | AcceptedSettlementInProcess |
ACSC | Terminal success |
RJCT | Terminal failure |
CANC | Cancelled |
5. Alias DICT
POST /v1/aliases — register
{
"alias": "cafemonkey@gerege",
"type": "MERCHANT",
"iban": "MN20910010000000XXXX",
"owner_attestation": "<JWS signed by PSP, containing merchant KYB metadata>"
}
owner_attestation JWS payload:
{
"iss": "GWMNUBXX",
"iat": 1714660800,
"exp": 1746196800,
"merchant": {
"name_hash": "<SHA-256 of legal name>",
"category_code": "5814",
"kyc_level": "QUALIFIED",
"registration_no": "1234567",
"registered_country":"MN"
}
}
GET /v1/aliases/{alias} — resolve
{
"alias": "cafemonkey@gerege",
"type": "MERCHANT",
"psp_bic": "GWMNUBXX",
"iban": "MN20910010000000XXXX",
"kyc_level": "QUALIFIED",
"merchant_name_display": "Cafe Monkey",
"category_code": "5814",
"verified_business": true,
"active": true
}
POST /v1/aliases/{alias}/verify — Confirmation of Payee
Мөнгө явуулахын өмнө сэндэр-ийн PSP alias resolve-аар expected name-аас тааруулдаг (anti-typo, anti-fraud).
Request: { "expected_name": "Cafe Monkey LLC" }
Response: { "match": "EXACT", "match_score": 1.0 }
// EXACT | CLOSE | NO_MATCH
6. PSP endpoint
POST /v1/psp/onboard — sandbox-ад
{
"name": "Test Wallet ABC",
"type": "EMI",
"country": "MN",
"contact_email": "tech@testwallet.mn",
"expected_use_cases": ["P2P", "P2M"],
"csr": "<base64 PEM CSR>"
}
Response (sandbox):
{
"bic_assigned": "TESTWALMN",
"client_cert": "<PEM cert for mTLS>",
"credentials": {
"client_id": "...",
"shared_secret_for_hmac": "..."
},
"sandbox_endpoints": "https://sandbox.paygrid.mn/v1/"
}
Production-аар onboarding: manual review, KYB, contract-аар. API-аар нээгдэхгүй.
GET /v1/psp/{bic}/balance — nostro position
{
"psp_bic": "GWMNUBXX",
"as_of": "2026-05-06T14:30:00Z",
"positions_by_counterparty": [
{
"counterparty_bic": "KHANUBXX",
"balance_minor": 5230000,
"currency": "MNT",
"settled_through": "2026-05-05T23:59:59Z",
"pending_in": 1500000,
"pending_out": 200000
}
],
"settlement_due": [
{
"date": "2026-05-06",
"net_position_minor": 4230000,
"status": "pending_eod"
}
]
}
7. Webhooks (PayGrid → PSP)
PayGrid async event-уудаар PSP-ын webhook URL-руу хүргэнэ.
POST https://psp.example.com/webhooks/paygrid
Content-Type: application/json
X-PayGrid-Signature: <HMAC-SHA256 of body using shared secret>
X-PayGrid-Event-ID: 550e8400-e29b-41d4-a716-446655440000
X-PayGrid-Event-Type: payment.completed
X-PayGrid-Timestamp: 2026-05-06T14:23:01Z
{
"event_id": "evt_550e8400...",
"event_type": "payment.completed",
"event_time": "2026-05-06T14:23:01Z",
"data": {
"paymentId": "p_paygrid_550e8400...",
"transactionStatus": "ACSC",
"settlementDateTime": "2026-05-06T14:23:01Z",
"uetr": "550e8400-e29b-41d4-a716-446655440000"
}
}
Event types
payment.status_changed | Status changed to non-terminal |
payment.completed | Status = ACSC (terminal success) |
payment.failed | Status = RJCT (terminal failure) |
payment.returned | Inbound pacs.004 (refund) |
alias.revoked | Alias revoked (sanctions, fraud) |
psp.balance_low | Nostro position approaching limit |
settlement.batch_completed | EOD batch settled at Mongolbank |
audit.alert | FRM raised alert involving this PSP |
Delivery semantics
- At-least-once delivery (PSP must be idempotent on Event-ID)
- Retry: exponential backoff, max 5 attempts over 24 цаг
- 5 алдаагаас хойш paused — manual intervention
- PSP must respond 2xx within 5 сек
- TLS 1.3 required, cert pinning supported
8. Алдааны код
| HTTP | Code | Тайлбар |
|---|---|---|
| 400 | invalid_request | Schema validation failed |
| 401 | unauthorized | mTLS or JWT failed |
| 403 | forbidden | Participant not authorized for this op |
| 404 | resource_not_found | Debtor IBAN not at known bank |
| 409 | idempotency_conflict | Same Idempotency-Key with different payload |
| 422 | unprocessable_entity | FRM hard block |
| 429 | too_many_requests | Rate limit exceeded |
| 500 | internal_error | Server fault |
| 503 | service_unavailable | Bank PISP API down |
Алдааны body Berlin Group tppMessages хэлбэртэй:
{
"tppMessages": [
{
"category": "ERROR",
"code": "FORMAT_ERROR",
"text": "Invalid IBAN checksum"
}
]
}
9. PayGrid NextGenPSD2 extensions
Pure Berlin Group-аас гадуурх Mongol-ын онцлогтой нэмэлтүүд:
а) binding_jws field on payment initiate
PSD2 RTS Article 5 Dynamic Linking — Wallet PSP canonical bytes-ыг JWS-ээр sign-аар payment request-аар оруулна. Bank SCA-аас өмнө verify хийнэ.
б) creditorAlias field
NextGenPSD2 alias concept-гүй. PayGrid extends — creditorAccount.iban-ын оронд creditorAlias-аар явуулж болно. PayGrid alias DICT-аас resolve хийгээд forward.
в) frm_score + frm_action response field
PayGrid FRM score-ыг PSP-руу буцааж UX-ыг informативлах боломж олгодог (warning, retry, etc.).
г) psp_attestation — KYC level
Гүйлгээ бүрд debtor + creditor KYC level бичигдсэн нь AML reporting-аар.
10. OpenAPI publication
Spec доорх URL-уудаас өмнөөс available:
https://api.paygrid.mn/.well-known/openapi/paygrid-v1.yaml
https://api.paygrid.mn/.well-known/openapi/paygrid-v1.json
CI-аас Go код-аас auto-generate (oapi-codegen-аар).
11. Rate limits
| Operation | Per-PSP limit |
|---|---|
| Bank PISP API call | 100 req/sec |
| Alias resolve | 500 req/sec |
| PSP balance query | 10 req/sec |
| QR resolve | 500 req/sec |
Бүх response-д headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: <unix epoch>
12. Idempotency
X-Idempotency-Keyбүх POST endpoint-аар required- 24-цагийн дедупликации цонх
- Same key + same payload → cached response
- Same key + different payload → 409 idempotency_conflict
- Storage: Redis 24-цагийн TTL
13. SDK target (Phase 2+)
github.com/paygrid-mn/paygrid-go Go
github.com/paygrid-mn/paygrid-node Node.js
github.com/paygrid-mn/paygrid-python Python
github.com/paygrid-mn/paygrid-android Android (NextGenPSD2 client)
github.com/paygrid-mn/paygrid-swift iOS
MIT licensed. CI-аас npm/pypi/maven publish.
Эх сурвалж: PLAN/05-API-SPEC.md, PLAN/12-CONFORMANCE.md.
Дараагийн хуудас: Аюулгүй байдал →