Files
nick-doc/03 - API Reference/API Overview.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

188 lines
8.4 KiB
Markdown

---
title: API Overview
tags: [api, reference, overview]
---
# API Overview
The AMN backend is an Express.js + TypeScript service that exposes a REST API plus a Socket.IO real-time channel. Every HTTP endpoint is mounted under `/api/<service>/...` in [`backend/src/app.ts`](../../backend/src/app.ts) and follows a consistent response envelope, authentication scheme, and error model.
This page is the entry point for the API. See the individual service pages for endpoint details:
- [[Authentication API]] - register/login/passkeys/Google OAuth
- [[User API]] - profile, wallet, admin user management
- [[Marketplace API]] - purchase requests, seller offers, templates, shop, reviews
- [[Payment API]] - SHKeeper, Web3, DePay, payouts
- [[Chat API]] - conversations and messages
- [[Notification API]] - in-app notifications
- [[Dispute API]] - dispute resolution *(planned, not yet implemented)*
- [[Blog API]] - blog posts *(planned, not yet implemented)*
- [[Admin API]] - user management, data cleanup *(planned, not yet implemented)*
- [[Points API]] - loyalty points, levels, referrals *(planned, not yet implemented)*
- [[AI API]] - OpenAI-backed text endpoints
- [[File API]] - upload, delete, serve
- [[Socket Events]] - real-time events
- [[Error Codes]] - status mapping and error shape
## Base URLs
| Environment | Base URL |
| --- | --- |
| Local development | `http://localhost:5001/api` |
| Staging / dev | `https://dev.amn.gg/api` |
| Production | `https://amn.gg/api` |
The base port is set via `PORT` env var; in `development` it defaults to `5001`. CORS is restricted to `process.env.FRONTEND_URL` and credentials are allowed (`cors({ origin, credentials: true })` in `app.ts`).
Health check (not under `/api`): `GET /health``{ success, message, timestamp, environment, version }`.
API discovery endpoint: `GET /api` → returns a map of available service prefixes.
## Versioning
The API is currently un-versioned (there is no `/v1` in paths). Breaking changes are communicated via release notes in the repository. The version string is exposed on `/health` and is sourced from `package.json` (`process.env.npm_package_version`). At the time of writing the deployed version is in the `4.x` line.
## Authentication
All protected endpoints use a stateless JWT in the standard HTTP Authorization header:
```
Authorization: Bearer <accessToken>
```
The token is verified by `authenticateToken` in [`backend/src/shared/middleware/auth.ts`](../../backend/src/shared/middleware/auth.ts) using `config.jwtSecret`. The decoded payload is normalised into `req.user = { id, email, role }` regardless of which key carried it (`id`, `userId`, `_id`, `sub`).
Tokens are issued by `POST /api/auth/login`, `POST /api/auth/google/signin`, `POST /api/auth/google/signup`, `POST /api/auth/passkey/authenticate`, and `POST /api/auth/refresh-token`. Refresh tokens are stored on the [[User]] document (`refreshTokens` array) so an admin password change wipes them and forces re-login.
Role-based access uses `authorizeRoles('admin', ...)` after `authenticateToken`. Three roles exist: `buyer`, `seller`, `admin`.
WebAuthn / Passkey flows live under `/api/auth/passkey/*` and exchange a challenge for an assertion; on success a regular JWT pair is returned (`tokens.accessToken`, `tokens.refreshToken`). See [[Authentication Flow]] for the full lifecycle.
## Standard response envelope
The canonical helper is `ResponseHandler` in [`backend/src/shared/utils/response-handler.ts`](../../backend/src/shared/utils/response-handler.ts). Successful responses look like:
```json
{
"success": true,
"message": "Success",
"data": { /* payload */ },
"statusCode": 200,
"timestamp": "2026-05-23T10:00:00.000Z",
"path": "/api/marketplace/purchase-requests",
"method": "GET",
"meta": { /* optional */ }
}
```
Paginated responses add a `pagination` block:
```json
{
"success": true,
"data": [ /* items */ ],
"pagination": {
"page": 1,
"limit": 20,
"total": 137,
"totalPages": 7,
"hasMore": true
}
}
```
Error responses use the same envelope with `success: false`:
```json
{
"success": false,
"message": "Validation failed",
"error": "Validation Error",
"statusCode": 400,
"timestamp": "2026-05-23T10:00:00.000Z",
"path": "/api/auth/register",
"method": "POST",
"data": [ /* validation details */ ]
}
```
Caveat: not every endpoint uses `ResponseHandler`. Legacy routes (mainly under `/api/users`, `/api/marketplace` legacy, `/api/payment/decentralized`, parts of `/api/payment/shkeeper`) return ad-hoc shapes such as `{ error: string }` on failure or bare objects on success. When in doubt consult the per-endpoint response section in the service pages. The error middleware in [`shared/middleware/errorHandler.ts`](../../backend/src/shared/middleware/errorHandler.ts) covers uncaught exceptions and emits `{ success: false, error, statusCode, stack? }`.
## Pagination conventions
Most list endpoints accept `?page=<n>&limit=<n>` query params:
- `page` defaults to `1`, 1-based.
- `limit` defaults vary (20 for notifications/marketplace, 50 for user lists) and is capped (e.g. 100 for templates).
- Server computes `total`, `totalPages`, and `hasMore` and returns them under `pagination`.
- Some endpoints also accept `offset` (e.g. payment lists) as a raw skip count.
Sort parameters: list endpoints commonly accept `sortBy` (default `createdAt`) and `sortOrder` (`asc` | `desc`, default `desc`).
## Common query params
| Parameter | Used by | Meaning |
| --- | --- | --- |
| `search` | users, templates, posts | Case-insensitive regex over title/name/email fields |
| `status` | payments, requests, disputes, notifications | Filter by entity state |
| `role` | users, contacts | Filter by `buyer`/`seller`/`admin` |
| `isActive` | users, templates | Boolean filter |
| `categoryId` | templates, requests | MongoId category filter |
| `unreadOnly` | notifications | Only unread items |
| `format` | payment export | `json` (default) or `csv` |
## Rate limiting
Rate limiting is **enabled** as of the 2026-05-24 remediation. Four tiers are active in `backend/src/app.ts`:
| Tier | Scope | Limit | Window |
| --- | --- | --- | --- |
| Global | All `/api/*` routes (except `/health` and Request-Network webhooks) | 100 req | 15 min per IP |
| Auth | `/api/auth/*` | 10 req | 15 min per IP |
| Payment | `/api/payment/*` | 30 req | 15 min per IP |
| AI | `/api/ai/*` | 20 req | 15 min per IP |
The Express `trust proxy` setting is enabled in production so the real client IP is read from `X-Forwarded-For` (Nginx terminator).
## CORS
CORS is configured globally in `app.ts`:
```ts
cors({
origin: process.env.FRONTEND_URL,
credentials: true,
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
})
```
Only the configured `FRONTEND_URL` may make cross-origin requests with credentials. The SHKeeper configuration endpoint (`GET /api/payment/shkeeper/config`) overrides this with `Access-Control-Allow-Origin: *` because it is consumed by the SHKeeper payment widget hosted on another domain.
Uploaded files served from `/uploads/*` use `helmet({ crossOriginResourcePolicy: { policy: "cross-origin" } })` so they can be embedded from the frontend domain.
## Real-time channel
Socket.IO runs on the same HTTP server. **All connections require a valid JWT** passed in `socket.auth.token` (or `socket.handshake.query.token`). The server verifies the token with `jwt.verify(config.jwtSecret)` before allowing the connection. Room-join events enforce strict membership checks:
- `join-user-room` — only the authenticated user may join their own room.
- `join-request-room` — buyer, preferred seller, or offer submitter only.
- `join-seller-room` / `join-buyer-room` — only the matching user id.
- `join-chat-room` — active participant only.
Clients join rooms via `join-user-room`, `join-request-room`, `join-seller-room`, `join-buyer-room`, `join-chat-room`. Full catalog: [[Socket Events]].
## Standard HTTP status codes
- `200 OK` - success
- `201 Created` - resource created
- `400 Bad Request` - validation error
- `401 Unauthorized` - missing/invalid token
- `403 Forbidden` - role/ownership failure
- `404 Not Found` - resource or route missing
- `409 Conflict` - duplicate (email, review)
- `423 Locked` - account locked (auth flows)
- `500 Internal Server Error` - unhandled exception
See [[Error Codes]] for the app-specific codes returned in the `error` field.