docs: align API reference and data model docs with code reality

API Reference (9 files updated):
- Marketplace API: corrected offer endpoints (scoped under /purchase-requests/:id/offers),
  marked phantom /search /stats /seller/:sellerId /withdraw routes as NOT IMPLEMENTED,
  documented PUT→PATCH mismatches, removed invalid SellerOffer 'active' status
- Dispute API: corrected resolve schema (action enum), categories (no 'fraud'),
  removed 'under_review' status, added security callouts (3 unguarded endpoints),
  route shadowing documented, all socket events marked as TODO stubs
- Notification API: corrected mark-all-read method+path, fixed broken GET /:id,
  added unread-count-update event, 90-day TTL documented
- Payment API: /create→/save, removed 10+ phantom endpoints, fixed release/refund
  paths (no /shkeeper/ segment), added 3 unauthenticated endpoint security warnings,
  stats undercounting documented, export privilege gap documented
- Authentication API: 8-digit→6-digit code, no-complexity warning on reset-with-code,
  rate limiter counts all attempts, passkey stub claims removed, deleteAccount bug noted
- Admin API: PUT→PATCH bug documented, wrong status values documented, hard vs soft
  delete clarified, scanner no-auth security bug, 3 NOT IMPLEMENTED endpoints
- Chat API: file upload wrong endpoint bug, archive PUT→PATCH bug, rate limits added
- Points API: corrected redeem schema, referral triggers on 'completed' only,
  leaderboard period ignored, removed 'refund' PointTransaction type
- Socket Events: removed request-cancelled, notification-read; added unread-count-update;
  dispute events all stubs; referral-signup is auth-domain not points-domain

Data Models (3 files updated):
- SellerOffer: removed 'active' from status enum, withdrawOffer() is dead code
- PurchaseRequest: added pending_payment/active statuses, added 'urgent' urgency,
  corrected description minimum (5 chars), removed finalized/archived
- Dispute: corrected action enum, categories (no fraud), removed under_review,
  security callout on unguarded status/resolve endpoints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-05-29 14:57:47 +04:00
parent a1f056e6a5
commit 9698ec5809
12 changed files with 287 additions and 75 deletions

View File

@@ -5,6 +5,8 @@ tags: [api, payment, reference, request-network, escrow]
# Payment API
> **Last updated:** 2026-05-29 — aligned with code (see [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md))
The payment surface is split across provider-neutral payment routers, Request Network checkout/webhook routes, derived-destination custody routes, and admin safety routes:
| Path prefix | File | Purpose |
@@ -92,11 +94,7 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip
**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.
> ⚠️ **NOT IMPLEMENTED:** `GET /payment/:id/status`, `POST /payment/:id/confirm`, and `DELETE /payment/:id` do not exist in the codebase. Do not call these paths.
### GET /api/payment/user/:userId
@@ -108,12 +106,16 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip
**Description:** Aggregated counts and sums per status.
**Auth required:** Bearer JWT
**⚠️ Known undercounting:** Only payments with status `'confirmed'` are counted as `successfulPayments`. Payments with status `'completed'` (the terminal state for SHKeeper and DePay) are **not** included in this count and are therefore under-reported.
### 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`
**⚠️ Privilege gap:** The controller-pattern route for this endpoint has no admin guard. Any authenticated user (not just admins) can export payment data.
> ⚠️ **NOT IMPLEMENTED:** `/payment/history`, `/payment/methods`, `/payment/validate`, `/payment/transactions`, and `/payment/escrow/balance` do not exist. Do not call these paths.
### POST /api/payment/payments/cleanup-pending
@@ -124,15 +126,20 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip
### 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
**⚠️ SECURITY — NO AUTHENTICATION:** This endpoint has no authentication guard. Any unauthenticated caller can trigger a blockchain re-query for any payment ID.
**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
**⚠️ SECURITY — NO AUTHENTICATION:** This endpoint has no authentication guard. Any unauthenticated caller can trigger a full database backfill scan.
**Request body:** `{ limit?: number }` (default 10)
### GET /api/payment/payments/:id/debug
**Description:** Debug bundle including the raw payment, blockchain metadata, and wallet-monitor status. Intended for admin / development.
**⚠️ SECURITY — NO AUTHENTICATION:** Despite exposing full payment data, this endpoint has no authentication guard. Any unauthenticated caller can retrieve complete payment details for any payment ID.
### POST /api/payment/callback
**Description:** Generic payment callback (called by the older client SDK).
@@ -175,6 +182,8 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip
**Auth required:** No (signature-protected)
**Response:** `200` when processed or duplicate; `202` when accepted but safety checks are pending; `401` for invalid signature.
> ⚠️ **NOT IMPLEMENTED:** `POST /api/payment/request-network/:id/payout/initiate`, `POST /api/payment/request-network/:id/payout/confirm`, `POST /api/payment/request-network/:id/release/confirm`, and `POST /api/payment/request-network/:id/refund/confirm` do not exist in the codebase. Do not call these paths.
## Legacy SHKeeper - Pay-in
> [!warning] Historical route family
@@ -218,11 +227,13 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip
**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).
- Updates the matching [[Payment]] to `completed` (`OVERPAID` and `PAID` both count). Note: `'completed'` is the terminal state for SHKeeper payments but is **not** counted as `successfulPayments` in `GET /api/payment/stats`.
- 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.
> ⚠️ **NOT IMPLEMENTED:** `GET /api/payment/shkeeper/status/:paymentId` does not exist. SHKeeper payment status is delivered via socket events only — there is no HTTP polling endpoint.
### 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.
@@ -270,25 +281,27 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip
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
**⚠️ Path correction:** The `/shkeeper/` segment is NOT present in the actual release/refund routes. The correct paths are under `/api/payment/:id/…` (not `/api/payment/shkeeper/:id/…`).
### POST /api/payment/: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
### POST /api/payment/: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
### POST /api/payment/: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
### POST /api/payment/:id/refund/confirm
**Description:** Records the refund tx hash; emits `purchase-request-update` (`type: payment_refunded`).
**Auth required:** Bearer JWT (admin)
@@ -332,7 +345,9 @@ Historical payouts were SHKeeper-side outbound transfers. Current routine releas
**Auth required:** No (signature checked)
**Response 200/400:** `{ success, message, data }`
## Legacy Web3 Wallet-Direct
## Legacy Web3 Wallet-Direct (DePay)
> ⚠️ **NOT IMPLEMENTED:** `POST /payment/depay/intents` (`createDePayIntent`) does not exist in the codebase.
### POST /api/payment/decentralized/save
@@ -377,7 +392,7 @@ Historical payouts were SHKeeper-side outbound transfers. Current routine releas
### POST /api/payment/decentralized/verify/:paymentId
**Description:** Re-verifies a single decentralized payment against the chain.
**Description:** Re-verifies a single decentralized payment against the chain. `paymentId` is a **path parameter** as shown.
**Auth required:** Bearer JWT (owner or admin)
### POST /api/payment/decentralized/verify-all-pending
@@ -491,8 +506,8 @@ Same result shape as above, but for a single destination.
- `pending` - intent created, awaiting on-chain settlement
- `processing` - settlement seen, awaiting confirmations
- `confirmed` - fully credited (intermediate; sometimes skipped)
- `completed` - confirmed, escrow funded
- `confirmed` - fully credited (intermediate; sometimes skipped). **Note:** this is the only status counted as `successfulPayments` in `GET /api/payment/stats`.
- `completed` - confirmed, escrow funded. Terminal state for SHKeeper and DePay. **Not** counted in `successfulPayments` stats — see stats undercounting note above.
- `failed` - intentionally failed (expired, declined, refused)
- `cancelled` - cancelled by user/admin
- `released` - escrow released to seller through the release/refund orchestration and custody signer
@@ -530,6 +545,8 @@ Escrow state (`escrowState`): `unfunded` → `funded` → `released` | `refunded
}
```
> ⚠️ **NOT IMPLEMENTED:** `GET /api/admin/settings/confirmation-thresholds/history` does not exist. Only the current-values GET and per-chain PATCH endpoints are implemented.
## Payments awaiting confirmation (admin)
### `GET /api/admin/payments/awaiting-confirmation`
@@ -586,11 +603,7 @@ Escrow state (`escrowState`): `unfunded` → `funded` → `released` | `refunded
}
```
### `POST /api/admin/rn/networks/reload`
**Auth:** Admin only
**Description:** Reload the in-memory chain + token registry from JSON files on disk. Call after editing `supportedChains.json` or `tokens.json` in the container.
**Response 200:** `{ "success": true, "message": "Registry reloaded from disk" }`
> ⚠️ **NOT IMPLEMENTED:** `POST /api/admin/rn/networks/reload` and `POST /api/admin/rn/networks/probe/:chainId` do not exist in the codebase.
## Related