-
Notifications
You must be signed in to change notification settings - Fork 0
API Reference
Base URL: http://localhost:3001
Swagger UI (interactive): http://localhost:3001/doc
OpenAPI JSON spec: http://localhost:3001/doc/json
All routes except /api/v1/system/health, POST /api/v1/auth/login, and GET /api/v1/auth/users require a Bearer JWT:
Authorization: Bearer <token>
Obtain a token via POST /api/v1/auth/login.
The backend is structured as domain modules, each owning its BIAN Service Domains, collections, and routes.
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ MODULE: identity — SD-16 Party Authentication │
│ Routes: /api/v1/auth/* │
│ Collection: partyAuthentication QE: equality on email │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ MODULE: customer — SD-53 Customer Agreement + SD-88 Payment Card │
│ Routes: /api/v1/customer · /api/v1/customer/:customerId/cards │
│ Collections: customerAgreement (QE:equality on email/phone/accountRef) │
│ customerAgreementSensitive (QE:none on address/govId) │
│ paymentCard (QE:none on expiry date) │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ MODULE: transactions — SD-254 Card Transaction │
│ Routes: /api/v1/transactions │
│ Collections: cardTransaction (QE:equality on accountRef) │
│ cardTransactionSensitive (QE:none on gateway payload) │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ MODULE: fraud — SD-83 Fraud Diagnosis │
│ Routes: /api/v1/fraud │
│ Collections: fraudDiagnosisCase (plaintext — no CHD) │
│ fraudDiagnosisCaseEvents (plaintext — audit log) │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ MODULE: gateway — SD-89+SD-64+SD-65+SD-57 Prototype (v5 roadmap) │
│ Routes: /api/v1/merchants · /api/v1/gateway/payments · /api/v1/gateway/tokens │
│ Collections: merchantAgreement (QE:none on apiKeyHash) │
│ paymentOrder (plaintext + TTL index) │
│ tokenVault (QE:none on networkToken) │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ MODULE: system — Infrastructure │
│ Routes: /api/v1/system/health · /api/v1/system/raw/:collection/:id │
│ No collections. Health: always available. Raw: non-production only. │
└────────────────────────────────────────────────────────────────────────────────────────┘
| Module | PCI CDE Scope | Reason |
|---|---|---|
customer |
In scope | Stores encrypted PII and CHD (expiry date) |
transactions |
In scope | Stores encrypted account reference and gateway payload |
gateway |
In scope | Stores merchant credentials and payment order references |
fraud |
Adjacent | References CDE keys via plaintext FK; no CHD stored |
identity |
Adjacent | Only encrypted email for auth lookup |
system |
Non-CDE | No data access in production |
| Method | Route | Auth | Description |
|---|---|---|---|
GET |
/ |
None | Redirect to /doc (Swagger UI) |
GET |
/api/v1/system/health |
None | API + Atlas health status |
GET |
/api/v1/system/raw/:collection/:id |
JWT | Raw ciphertext view — non-production only (403 in prod) |
| Method | Route | Auth | Description |
|---|---|---|---|
POST |
/api/v1/auth/login |
None | Authenticate and obtain JWT. QE:equality search on email. |
GET |
/api/v1/auth/users |
None | List pre-seeded demo users (no passwords). |
Demo users:
| Role | |
|---|---|
luis.fernandez@leafybank.demo |
customer |
julia.santos@leafybank.demo |
customer |
sarah.chen@leafybank.demo |
level1_analyst |
michael.obi@leafybank.demo |
level2_investigator |
admin@leafybank.demo |
security_auditor |
Password for all: demo-password
| Method | Route | Auth | Description |
|---|---|---|---|
GET |
/api/v1/customer?email=<v> |
JWT | QE:equality search on customerEmailAddress
|
GET |
/api/v1/customer?phone=<v> |
JWT | QE:equality search on customerMobilePhoneNumber
|
GET |
/api/v1/customer?accountRef=<v> |
JWT | QE:equality search on customerAgreementReference
|
Encrypted fields (
customerEmailAddress,customerMobilePhoneNumber,customerAgreementReference) are never echoed in the response — only used as predicates.
Response 200:
{
"customerAgreementInstanceReference": "uuid-v4",
"customerName": "Luis Fernandez",
"customerSegment": "retail",
"customerAgreementStatus": "active"
}Cards are a sub-resource of Customer Agreement — they belong to the customer, not to transactions.
| Method | Route | Auth | Description |
|---|---|---|---|
GET |
/api/v1/customer/:customerId/cards |
JWT | List payment cards for a customer |
POST |
/api/v1/customer/:customerId/cards |
JWT | Register a tokenized card for a customer |
:customerId = customerAgreementInstanceReference from the customer search above.
POST body:
{
"cardToken": "tok_abc123",
"paymentCardExpirationDate": "12/28",
"paymentCardMaskedPanDisplay": "****-****-****-1234",
"paymentCardNetwork": "VISA",
"paymentCardIsPreferred": false
}
paymentCardExpirationDateis stored as QE:none (CHD). CVV and PIN are never accepted at any endpoint.
| Method | Route | Auth | Description |
|---|---|---|---|
POST |
/api/v1/transactions |
JWT | Create a card transaction. Auto-triggers fraud case if amount or MCC matches risk criteria. |
GET |
/api/v1/transactions/:id |
JWT | Get transaction by UUID. cardTransactionAccountReference decrypted in API memory. |
GET |
/api/v1/transactions?cardToken=<v> |
JWT | List transactions by card token (standard index — token is NOT CHD). |
Auto fraud-case rule: A fraudDiagnosisCase is opened when amount > FRAUD_AMOUNT_THRESHOLD (default 500) OR MCC is in the risk list (5812, 6011, 7995).
POST body:
{
"cardToken": "tok_abc123",
"accountReference": "ACC-001",
"amount": 850.00,
"currency": "USD",
"cardTransactionMerchantName": "TechStore Online",
"cardTransactionMerchantCategoryCode": "5732",
"cardTransactionChannel": "online",
"cardTransactionMaskedPanDisplay": "****-****-****-1234",
"gatewayPayload": {}
}| Method | Route | Auth | Description |
|---|---|---|---|
GET |
/api/v1/fraud |
JWT | Paginated fraud case list. Filters: status, severity, page, limit. |
GET |
/api/v1/fraud/:id |
JWT | Full case detail with embedded transactionSnapshot. |
PATCH |
/api/v1/fraud/:id |
JWT | Update status, notes, or analyst assignment. |
POST |
/api/v1/fraud/:id/escalate |
JWT | Escalate to Level 2. (v2: issues DEK-sensitive token) |
GET |
/api/v1/fraud/:id/events |
JWT | Chronological audit event log from fraudDiagnosisCaseEvents. (v2)
|
BIAN lifecycle: open → under_review → escalated → resolved_cleared / resolved_fraud → closed
Event types: case_opened · assigned · note_added · field_accessed · escalated · ai_review · resolved · closed
PATCH body:
{
"fraudDiagnosisCaseStatus": "under_review",
"fraudDiagnosisAnalystInstanceReference": "uuid-of-analyst",
"caseNotes": "Suspicious merchant. Verifying with customer."
}All gateway endpoints return stub responses. Full persistence scheduled for v5. JWT required on all routes.
| Method | Route | Description |
|---|---|---|
GET |
/api/v1/merchants |
List merchants. Filters: status, mcc. |
POST |
/api/v1/merchants |
Onboard merchant. Returns merchantApiKey once (stored as QE:none hash). |
GET |
/api/v1/merchants/:id |
Merchant profile. merchantApiKeyHash never returned. |
PATCH |
/api/v1/merchants/:id |
Update limit, webhook URL, settlement schedule, or status. |
POST |
/api/v1/merchants/:id/webhooks |
Register webhook endpoint for payment event callbacks. |
| Method | Route | Description |
|---|---|---|
POST |
/api/v1/gateway/payments |
Create payment order. X-Idempotency-Key header required.
|
GET |
/api/v1/gateway/payments/:id |
Get order status + routing decision. |
POST |
/api/v1/gateway/payments/:id/confirm |
Link customer; initiated → confirmed. |
POST |
/api/v1/gateway/payments/:id/authorize |
SD-65 routing; creates cardTransaction; confirmed → authorized. |
POST |
/api/v1/gateway/payments/:id/capture |
Capture funds; authorized → captured. |
DELETE |
/api/v1/gateway/payments/:id |
Void; `authorized |
POST |
/api/v1/gateway/payments/:id/refund |
Partial or full refund; captured → refunded. |
Payment lifecycle:
initiated → confirmed → authorized → captured → settled
↘ voided
↘ voided
↘ refunded
| Method | Route | Description |
|---|---|---|
POST |
/api/v1/gateway/tokens |
Create token vault entry. Returns tokenVaultCardToken (surrogate, not CHD). |
GET |
/api/v1/gateway/tokens/:token |
Token metadata. tokenVaultNetworkToken (QE:none) never returned. |
{ "error": "Human-readable message" }| Code | Meaning |
|---|---|
400 |
Bad request — missing or invalid fields |
401 |
Missing or invalid Bearer JWT |
403 |
Forbidden — e.g. raw endpoint in production |
404 |
Resource not found |
409 |
Conflict — duplicate idempotency key |
422 |
Invalid state transition |
500 |
Unexpected server error |
503 |
Atlas unavailable — degraded mode |
| Rule | Enforcement mechanism |
|---|---|
| Full PAN never stored | Frontend tokenizes (tok_<uuid>) before calling POST /api/v1/transactions
|
| CVV / PIN never stored | Not accepted at any endpoint (no field in any request schema) |
| SAD never retained after auth |
cardTransactionSensitive.rawGatewayPayload stores only the gateway JSON response |
| QE:equality fields not echoed |
customerEmailAddress, customerMobilePhoneNumber, customerAgreementReference stripped from all GET responses |
merchantApiKeyHash never exposed |
All GET /merchants responses strip this field |
tokenVaultNetworkToken never exposed |
All GET /gateway/tokens responses strip this field |
| Level 2 field gating |
customerAgreementSensitive (address, govId) only accessible with DEK-sensitive — v2 escalation token |