Skip to content

API Reference

Antonio Membrides Espinosa edited this page May 29, 2026 · 6 revisions

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.


Component Map

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.                    │
└────────────────────────────────────────────────────────────────────────────────────────┘

PCI CDE scope by module

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

Complete Endpoint Map

system module

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)

auth tag — identity module (SD-16)

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:

Email 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


customer tag — customer module (SD-53)

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 tag — customer module (SD-88)

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
}

paymentCardExpirationDate is stored as QE:none (CHD). CVV and PIN are never accepted at any endpoint.


transactions tag — transactions module (SD-254)

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": {}
}

fraud tag — fraud module (SD-83)

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: openunder_reviewescalatedresolved_cleared / resolved_fraudclosed

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."
}

gateway tag — gateway module (SD-89 · SD-64 · SD-65 · SD-57) ⚠️ v5 Prototype

All gateway endpoints return stub responses. Full persistence scheduled for v5. JWT required on all routes.

Merchant Relations — SD-89

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.

Payment Order — SD-64 + SD-65 (Routing)

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

Token Vault — SD-57

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 response format

{ "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

PCI DSS controls enforced by the API

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

Clone this wiki locally