Files
nick-doc/03 - API Reference/Payment API.md
Siavash Sameni 4cf5c49274 docs(audit): align documentation with post-remediation backend reality
- Update data model enums to match backend models
- Update API reference auth requirements
- Add dispute module references and warning blocks
- Add 2026-05-24 audit remediation callout to Overview
- Generate task breakdowns and audit artifacts
- Add doc alignment report (.taskmaster/reports/)
2026-05-24 11:16:29 +04:00

14 KiB

title, tags
title tags
Payment API
api
payment
reference
shkeeper

Payment API

The payment surface is split across four routers, all mounted under /api/payment/*:

Path prefix File Purpose
/api/payment/* paymentControllerRoutes.ts New controller pattern (CRUD + configuration)
/api/payment/* paymentRoutes.ts Additional legacy endpoints (tx fetch, exports)
/api/payment/decentralized/* decentralizedPaymentRoutes.ts DePay / Web3 confirmations
/api/payment/shkeeper/* shkeeper/shkeeperRoutes.ts SHKeeper pay-in, webhook, release/refund
/api/payment/shkeeper/payout* shkeeper/shkeeperPayoutRoutes.ts SHKeeper payouts to sellers

Core model: Payment. Coordination logic to avoid race conditions when multiple sources update the same payment is in paymentCoordinator.ts.

Configuration / health

POST /api/payment/configuration

Description: Returns the payment provider configuration the SHKeeper widget needs (accepted blockchains, escrow receiver address, redirect URLs, webhook URL). Auth required: No Request body: { amount?, currency?, purchaseRequestId? } (used to scope returned config) Response 200:

{
  "accept": [{ "blockchain": "bsc", "token": "0x55d3...", "receiver": "0xa30..." }],
  "redirect": { "success": "...", "cancel": "..." },
  "webhook": "https://.../api/payment/shkeeper/webhook"
}

GET /api/payment/health

Description: Lightweight health probe. Auth required: No Response 200: { success, message, endpoints: { shkeeper, decentralized, health } }

GET /api/payment/shkeeper/config

Description: Same payload as /configuration but tailored for the SHKeeper-hosted widget; includes explicit CORS * headers. Auth required: No

Payment records (CRUD)

POST /api/payment

Description: Create a payment record (manual entry — usually the SHKeeper intent path is preferred). Auth required: Bearer JWT Request body:

{
  purchaseRequestId: string;
  sellerOfferId: string;
  buyerId: string;
  sellerId: string;
  amount: { amount: number; currency: string };
  blockchain?: { network: string; token: string };
  metadata?: Record<string, unknown>;
}

Response 201: { /* Payment document */ }

PUT /api/payment/:id

Description: Update a payment record (status, transactionHash, metadata). Auth required: Bearer JWT Request body:

{
  status?: "pending" | "processing" | "completed" | "failed" | "cancelled";
  transactionHash?: string;
  blockchain?: { ... };
  metadata?: Record<string, unknown>;
}

GET /api/payment

Description: List the caller's payments (defaults to completed,success status). Auth required: Bearer JWT Query params: status, limit (default 50), offset (default 0)

GET /api/payment/:id

Description: Fetch a payment by id. Auth required: Bearer JWT Errors: 404 not found.

GET /api/payment/:id/debug

Description: Debug bundle including the raw payment, blockchain metadata, and wallet-monitor status. Auth required: Bearer JWT Notes: Intended for admin / development.

GET /api/payment/user/:userId

Description: Payments for a specific user (admin or self). Auth required: Bearer JWT Query params: status, limit, offset

GET /api/payment/stats / GET /api/payment/stats/:userId

Description: Aggregated counts and sums per status. Auth required: Bearer JWT

GET /api/payment/export / GET /api/payment/export/:userId

Description: Export payments as json or csv. Auth required: Bearer JWT Query params: format=json|csv

POST /api/payment/payments/cleanup-pending

Description: Admin cleanup of stale pending payments. Auth required: Bearer JWT (admin) Response 200: { success, deletedCount, message }

POST /api/payment/payments/:id/fetch-tx

Description: Re-queries the blockchain to fetch the missing transactionHash for a completed payment. Auth required: Bearer JWT Response 200: { success, transactionHash, network, source, message }

POST /api/payment/payments/auto-fetch-missing

Description: Batch tx-hash backfill across the database. Auth required: Bearer JWT Request body: { limit?: number } (default 10)

POST /api/payment/callback

Description: Generic payment callback (called by the older client SDK). Auth required: No (verified by paymentRef matching) Request body: { paymentId, transactionHash, status, data }

POST /api/payment/verify

Description: Frontend verification endpoint used by the Web3 flow. Confirms a payment and updates the related PurchaseRequest. Auth required: Bearer JWT

SHKeeper - Pay-in

POST /api/payment/shkeeper/intents

Description: Creates a SHKeeper pay-in intent. The server provisions an invoice on SHKeeper, stores a Payment with provider: "shkeeper", direction: "in", returns the hosted-widget URL. Auth required: Bearer JWT (buyer) Request body:

{
  purchaseRequestId: string;
  sellerOfferId: string;
  amount: number;
  sellerId: string;
  token?: string;     // default "USDT"
  network?: string;   // default "bsc"
  metadata?: Record<string, unknown>;
}

Response 200:

{
  "success": true,
  "data": {
    "paymentId": "...",
    "paymentUrl": "https://pay.amn.gg/invoice/...",
    "externalId": "AMN_...",
    "expiresAt": "2026-05-23T11:00:00.000Z"
  }
}

Errors: 400 missing fields, 401 not authenticated, 500 SHKeeper error. Side effects: Emits payment-created globally and to the request room.

POST /api/payment/shkeeper/webhook

Description: SHKeeper posts here when an invoice changes state. Handles both raw-string and JSON bodies and verifies the HMAC signature (x-shkeeper-signature against the raw body using SHKEEPER_WEBHOOK_SECRET). Auth required: No (signature-protected) Body: The SHKeeper callback envelope (external_id, crypto, addr, fiat, balance_fiat, balance_crypto, paid, status, transactions[]). Response 200: { success: true } Side effects:

  • Updates the matching Payment to completed (OVERPAID and PAID both count).
  • Releases or rejects SellerOffer siblings (the chosen offer becomes accepted, others rejected).
  • Updates PurchaseRequest status to payment / processing.
  • Emits seller-offer-update to each affected seller room and purchase-request-update to the request room.

POST /api/payment/shkeeper/confirm-transaction

Description: Manual fallback when the webhook misses — the frontend calls this after the buyer signs the EVM transaction directly. Coordinated through PaymentCoordinator to avoid double updates. Auth required: Bearer JWT Request body: { paymentId, transactionHash, network? } Response 200: { success, message, data: { paymentId, transactionHash, status } } Side effects: Closes the SHKeeper invoice session, then runs the same offer/request updates as the webhook.

POST /api/payment/shkeeper/test

Description: Smoke-tests the real SHKeeper API. Development only. Auth required: No

POST /api/payment/shkeeper/callback-test (and GET equivalent)

Description: Echo-style endpoints used during webhook configuration. Auth required: No

POST /api/payment/shkeeper/create-test-payment

Description: Inserts a sample Payment row to exercise the webhook handler. Auth required: No

POST /api/payment/shkeeper/trigger-webhook

Description: Sends a fake webhook payload to the local webhook endpoint for end-to-end testing. Auth required: Bearer JWT

GET /api/payment/shkeeper/wallet-monitor/status

Description: Returns the wallet-monitor state (isMonitoring, watched wallet addresses). Auth required: No

GET /api/payment/shkeeper/auto-webhook/status

Description: Returns the auto-webhook fallback monitor state. Auth required: No

GET /api/payment/shkeeper/webhook-stats

Description: Counters for webhook deliveries (success / failure / duplicates). Auth required: Bearer JWT (admin)

SHKeeper - Release / Refund (escrow)

These build an admin-signed transaction off-chain and require a follow-up confirm with the broadcast tx hash. Source: shkeeperService.buildAdminSignedTxPayload and confirmAdminTx.

POST /api/payment/shkeeper/:id/release

Description: Prepares the admin-signed payload to release escrow to the seller. Returns the raw payload — the admin client signs and broadcasts. Auth required: Bearer JWT (admin) Response 200: { success: true, data: { /* tx payload */ } }

POST /api/payment/shkeeper/:id/release/confirm

Description: Records the broadcast transaction hash for the release; marks the payment as released, updates PurchaseRequest to seller_paid and emits purchase-request-update (type: payment_released). Auth required: Bearer JWT (admin) Request body: { txHash: string } Errors: 400 missing txHash.

POST /api/payment/shkeeper/:id/refund

Description: Mirror of release, but returns the escrow to the buyer. Auth required: Bearer JWT (admin)

POST /api/payment/shkeeper/:id/refund/confirm

Description: Records the refund tx hash; emits purchase-request-update (type: payment_refunded). Auth required: Bearer JWT (admin) Request body: { txHash: string }

SHKeeper - Payouts

Payouts are SHKeeper-side outbound transfers (admin pays the seller from a hot wallet).

POST /api/payment/shkeeper/payout

Description: Create a payout task. The server creates a Payment row with direction: "out" and provider task id, then returns the SHKeeper task descriptor. Auth required: Bearer JWT (admin) Request body:

{
  purchaseRequestId: string;
  sellerOfferId: string;
  buyerId: string;
  sellerId: string;
  amount: number;
  recipientAddress: string;
  token?: string;     // default "USDT"
  network?: string;   // default "bsc"
  metadata?: Record<string, unknown>;
}

Response 200: { success, data: { payoutId, taskId, status }, message } Side effects: emitGlobalEvent('payout-created', { ... }). Errors: 400 for each missing required field, 500 upstream error.

GET /api/payment/shkeeper/payout/status/:taskId

Description: Polls SHKeeper for the current task status. Auth required: Bearer JWT Response 200: { success, data: { /* status payload */ } }

POST /api/payment/shkeeper/payout/webhook

Description: SHKeeper webhook for payout state changes. Handled by processPayoutWebhookEvent. Emits payout-completed (or payout-updated) global socket events on success. Auth required: No (signature checked) Response 200/400: { success, message, data }

DePay / Web3 (decentralized)

POST /api/payment/decentralized/save

Description: Persists a Web3-initiated payment record. Auth required: Bearer JWT (enforces userId ownership match) Request body:

{
  purchaseRequestId: string;
  buyerId: string;
  sellerId?: string;
  amount: number;
  currency?: string;
  transactionHash?: string;
  network?: string;
  token?: string;
  walletAddress?: string;
  metadata?: Record<string, unknown>;
}

GET /api/payment/decentralized/status/:paymentId

Description: Returns the latest status for a decentralized payment. Auth required: No

PUT /api/payment/decentralized/update

Description: Update a decentralized payment's status / confirmations. Auth required: Bearer JWT (owner or admin) Request body: { paymentId, status, confirmations? }

GET /api/payment/decentralized/receiver

Description: Returns the configured escrow receiver wallet address. Auth required: No

GET /api/payment/decentralized/history/:userId

Description: Decentralized payment history for a user. Auth required: Bearer JWT (self or admin)

POST /api/payment/decentralized/verify/:paymentId

Description: Re-verifies a single decentralized payment against the chain. Auth required: Bearer JWT (owner or admin)

POST /api/payment/decentralized/verify-all-pending

Description: Iterates all pending decentralized payments and re-verifies them. Auth required: Bearer JWT (admin only)

POST /api/payment/decentralized/admin-payout

Description: Pay a seller directly from an admin hot wallet (no SHKeeper). Auth required: Bearer JWT (admin) Request body:

{
  purchaseRequestId: string;
  receiverWalletAddress: string;
  amount: number;
  currency?: string;     // default "USDT"
  network?: string;      // default "BSC"
}

Response 200: { success, data: { /* payout receipt */ } }

Status model

Payment uses the statuses below across all providers:

  • pending - intent created, awaiting on-chain settlement
  • processing - settlement seen, awaiting confirmations
  • confirmed - fully credited (intermediate; sometimes skipped)
  • completed - confirmed, escrow funded
  • failed - intentionally failed (expired, declined, refused)
  • cancelled - cancelled by user/admin
  • released - escrow released to seller (shkeeper flow)
  • refunded - escrow returned to buyer

Escrow state (escrowState): unfundedfundedreleased | refunded.