PayGrid · paygrid.mn

Танилцуулга / 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

RCVDReceived
PDNGPending
ACTCAcceptedTechnicalValidation
ACFCAcceptedFundsChecked
ACSPAcceptedSettlementInProcess
ACSCTerminal success
RJCTTerminal failure
CANCCancelled

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_changedStatus changed to non-terminal
payment.completedStatus = ACSC (terminal success)
payment.failedStatus = RJCT (terminal failure)
payment.returnedInbound pacs.004 (refund)
alias.revokedAlias revoked (sanctions, fraud)
psp.balance_lowNostro position approaching limit
settlement.batch_completedEOD batch settled at Mongolbank
audit.alertFRM 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. Алдааны код

HTTPCodeТайлбар
400invalid_requestSchema validation failed
401unauthorizedmTLS or JWT failed
403forbiddenParticipant not authorized for this op
404resource_not_foundDebtor IBAN not at known bank
409idempotency_conflictSame Idempotency-Key with different payload
422unprocessable_entityFRM hard block
429too_many_requestsRate limit exceeded
500internal_errorServer fault
503service_unavailableBank 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

OperationPer-PSP limit
Bank PISP API call100 req/sec
Alias resolve500 req/sec
PSP balance query10 req/sec
QR resolve500 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. Дараагийн хуудас: Аюулгүй байдал →