API Design Reference
Related docs:
Payment Architecture·Data Models·Security Compliance·Microservices
1. Conventions
| Convention | Value |
|---|---|
| Base path | /api/v1/ |
| Data format | application/json |
| Authentication | Authorization: Bearer <accessToken> |
| Gateway headers | x-pakashop-key (external) or x-internal-key (internal) |
| Error format | { "success": false, "error": "...", "code": "...", "message": "...", "details": {} } |
| Success format | { "success": true, "data": { ... } } or top-level object |
| Currency | ZMW; represented as number (decimal), displayed as K xxx.xx |
| Dates | ISO 8601 strings (2026-05-12T10:00:00.000Z) |
| Rate limit headers | X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset |
1.1 Centralised Error Codes
All errors use codes from shared/constants/errors.js:
const ErrorCodes = {
// Authentication
AUTH_001: { status: 401, message: 'Authentication required' },
AUTH_002: { status: 403, message: 'Insufficient permissions' },
AUTH_003: { status: 401, message: 'Invalid internal API key' },
MFA_001: { status: 403, message: 'Multi-factor authentication required' },
MFA_002: { status: 400, message: 'Invalid MFA code' },
// Validation
VAL_001: { status: 400, message: 'Validation error' },
VAL_002: { status: 400, message: 'Invalid phone number format' },
// Orders
ORDER_001: { status: 404, message: 'Order not found' },
ORDER_002: { status: 409, message: 'Order cannot be cancelled' },
// Payments
PAY_001: { status: 400, message: 'Payment processing failed' },
PAY_002: { status: 409, message: 'Duplicate payment attempt' },
PAY_003: { status: 402, message: 'Payment required' },
// Fraud
FRAUD_001: { status: 403, message: 'Transaction blocked by fraud detection' },
// Rate Limiting
RATE_001: { status: 429, message: 'Too many requests' },
// Generic
NOT_FOUND: { status: 404, message: 'Resource not found' },
INTERNAL: { status: 500, message: 'Internal server error' },
};
2. Authentication Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /auth/register | None | Register with email + password |
POST | /auth/login | None | Login; returns accessToken + refreshToken |
POST | /auth/logout | Required | Invalidate current session |
POST | /auth/refresh | None | Exchange refreshToken for new accessToken |
POST | /auth/request-magic-link | None | Send magic link to email |
POST | /auth/verify-magic-link | None | Verify magic link token |
POST | /auth/request-password-reset | None | Send password reset email |
POST | /auth/reset-password | None | Complete password reset |
POST | /auth/verify-email | None | Verify email with token |
GET | /auth/me | Required | Get authenticated user profile |
GET | /oauth/:provider | None | Initiate OAuth flow |
GET | /oauth/:provider/callback | None | OAuth callback |
2.1 MFA Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /auth/mfa/setup | Required | Begin MFA enrollment |
POST | /auth/mfa/verify-setup | Required | Verify MFA setup code |
POST | /auth/mfa/challenge | Partial (mfa_login token) | Request MFA challenge |
POST | /auth/mfa/verify-login | Partial (mfa_login token) | Verify MFA code and complete login |
DELETE | /auth/mfa/disable | Required + MFA | Disable MFA (requires verification) |
3. Product Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /products | None | List products with filters |
GET | /products/:id | None | Single product with variants |
GET | /products/recommendations | Optional | Personalised or popular products |
GET | /products/:productId/options | None | Product option groups |
GET | /products/:productId/variants | None | Product variants |
GET | /products/:productId/wholesale-tiers | None | Wholesale pricing tiers |
Query params for /products: category, search, minPrice, maxPrice, sort, page, limit, featured, shopId, pricingModel.
4. Shop Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /shops | None | List approved shops |
GET | /shops/search | None | Full-text shop search |
GET | /shops/slug/:slug | None | Shop by slug |
POST | /shops/request | Required | Request new shop (legacy flow) |
GET | /shops/my-shops | Required | Authenticated user's shops |
GET | /shops/:shopId/stats | Required | Shop analytics |
POST | /shops/:shopId/products | Required | Create product in shop |
GET | /shops/:shopId/products | Required | List shop's own products |
PUT | /shops/:shopId/products/:id | Required | Update product |
DELETE | /shops/:shopId/products/:id | Required | Soft-delete product |
GET | /shops/:shopId/inventory | Required | View inventory |
POST | /shops/:shopId/inventory/adjust | Required | Adjust stock |
GET | /shops/:shopId/settlements | Required | View settlement history |
5. Order Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /orders | Required | Create order |
GET | /orders/my | Required | Authenticated user's orders |
GET | /orders/:id | Required | Single order details |
PATCH | /orders/:id/cancel | Required | Cancel order |
GET | /orders/:id/tracking | Required | Get delivery tracking snapshot |
GET | /orders/:id/receipt | Required | Generate PDF receipt |
POST /orders request body:
{
"items": [
{
"productId": "uuid",
"shopId": "uuid",
"quantity": 2,
"price": 125.00,
"variantId": "uuid"
}
],
"shippingAddress": {
"firstName": "John",
"lastName": "Banda",
"email": "john@example.zm",
"phone": "0977123456",
"address": "Plot 123, Cairo Road",
"city": "Lusaka",
"province": "Lusaka",
"country": "Zambia"
},
"paymentMethod": "MTN_MONEY",
"couponCode": "SUMMER2026",
"loyaltyPointsToRedeem": 500,
"total": 250.00
}
6. Payment Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /payments/initiate | Required | Initiate payment for an order |
GET | /payments/status/:orderId | Required | Get payment + settlement status |
POST | /payments/webhook/:provider | None | Receive gateway webhooks |
POST | /payments/release/:orderId | Admin | Manually release vendor funds |
POST | /payments/refund/:orderId | Admin | Process refund |
POST /payments/initiate
Request:
{
"orderId": "uuid",
"paymentMethod": "MTN" | "AIRTEL" | "ZAMTEL" | "CARD",
"phoneNumber": "0977123456"
}
Response — mobile money:
{
"success": true,
"data": {
"transactionId": "pawa-debit-abc123",
"provider": "PAWAPAY",
"type": "ussd",
"message": "A payment request has been sent to 0977123456. Please enter your PIN."
}
}
Response — card:
{
"success": true,
"data": {
"redirectUrl": "https://checkout.flutterwave.com/v3/hosted/pay/...",
"provider": "FLUTTERWAVE",
"type": "redirect"
}
}
GET /payments/status/:orderId
Response:
{
"success": true,
"data": {
"settlement": { "settlementStatus": "HELD" },
"payments": [
{
"id": "uuid",
"gateway": "PAWAPAY",
"status": "CAPTURED",
"amount": 250.00,
"currency": "ZMW",
"createdAt": "2026-05-12T10:00:00Z"
}
],
"fraudCheck": {
"score": 12,
"status": "PASSED"
}
}
}
Frontend maps
status === 'CAPTURED'→paymentStatus = 'PAID'.
7. Notification Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /notifications | Required | List user's notifications |
PATCH | /notifications/:id/read | Required | Mark as read |
PATCH | /notifications/read-all | Required | Mark all as read |
GET | /notifications/preferences | Required | Get user preferences |
PUT | /notifications/preferences | Required | Update preferences |
GET | /notifications/stream | Required | SSE real-time notification stream |
8. Seller Application Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /seller-applications | Required | Create application draft |
GET | /seller-applications/my-application | Required | Get own application |
PUT | /seller-applications/:id/phase/:phase | Required | Update a phase |
POST | /seller-applications/:id/documents | Required | Upload KYC documents |
POST | /seller-applications/:id/submit | Required | Submit for review |
GET | /seller-applications | Admin | List all applications |
PUT | /seller-applications/:id/status | Admin | Update application status |
POST | /seller-applications/:id/approve | Admin | Approve; create shop |
9. Delivery Endpoints
9.1 Agent Operations
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /delivery/apply | Required | Submit delivery agent application |
GET | /delivery/agent/me | Required | Get current agent profile |
PATCH | /delivery/agent/availability | Required | Toggle availability |
GET | /delivery/agent/deliveries | Required | Get assigned deliveries |
POST | /delivery/agent/confirm | Required | PIN-based delivery confirmation (Tier 1) |
POST | /delivery/signature/:id/capture | Required | Digital signature capture (Tier 2) |
9.2 Courier Company Operations
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /delivery/courier/agents | Required (FLEET_MANAGER) | List sub-agents |
POST | /delivery/courier/agents | Required (FLEET_MANAGER) | Add sub-agent |
DELETE | /delivery/courier/agents/:id | Required (FLEET_MANAGER) | Remove sub-agent |
9.3 Admin Operations
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /delivery/admin/applications | Admin | List pending applications |
GET | /delivery/admin/agents | Admin | List all verified agents |
PATCH | /delivery/admin/agents/:id/approve | Admin | Approve application |
PATCH | /delivery/admin/agents/:id/reject | Admin | Reject with reason |
PATCH | /delivery/admin/agents/:id/suspend | Admin | Suspend agent |
PATCH | /delivery/admin/agents/:id/activate | Admin | Re-activate agent |
10. Tracking Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /tracking/location | Required (DELIVERY_AGENT) | Post GPS location |
GET | /tracking/:orderId/current | Required | Get tracking snapshot |
GET | /tracking/:orderId/history | Required | Get event timeline |
GET | /tracking/:orderId/eta | Required | Get/recalculate ETA |
GET | /tracking/admin/active | Admin | All active deliveries |
WS | /tracking/ws | Required | WebSocket connection for live tracking |
11. Coupon Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /coupons | Required (SHOP_OWNER) | Create coupon |
GET | /coupons | None | List available coupons |
GET | /coupons/:id | None | Get coupon details |
PUT | /coupons/:id | Required (SHOP_OWNER) | Update coupon |
DELETE | /coupons/:id | Required (SHOP_OWNER) | Deactivate coupon |
POST | /coupons/:id/validate | Required | Validate coupon for cart |
12. Loyalty Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /loyalty/points | Required | Get current points balance |
GET | /loyalty/history | Required | Get points transaction history |
POST | /loyalty/redeem | Required | Redeem points for discount |
GET | /loyalty/shop/:shopId | Required | Get shop-specific loyalty program |
13. Fraud Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /fraud/queue | Required (FRAUD_ANALYST, PLATFORM_ADMIN) | List pending reviews |
POST | /fraud/queue/:id/approve | Required (FRAUD_ANALYST, PLATFORM_ADMIN) | Approve blocked transaction |
POST | /fraud/queue/:id/reject | Required (FRAUD_ANALYST, PLATFORM_ADMIN) | Reject blocked transaction |
GET | /fraud/rules | Required (PLATFORM_ADMIN) | List fraud rules |
PUT | /fraud/rules/:id | Required (PLATFORM_ADMIN) | Update fraud rule |
14. Admin Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /admin/users | Admin | List all users |
PATCH | /admin/users/:id/role | Admin | Update user role |
GET | /admin/analytics | Admin | Platform-wide analytics |
GET | /admin/reconciliation | Admin | Financial reconciliation report |
POST | /admin/broadcast | Admin | Send broadcast notification |
GET | /admin/feature-flags | Admin | List feature flags |
PUT | /admin/feature-flags/:key | Admin | Toggle feature flag |
GET | /admin/moderation/flags | Admin, MODERATOR | List flagged content |
POST | /admin/moderation/flags/:id/approve | Admin, MODERATOR | Approve flagged content |
POST | /admin/moderation/flags/:id/reject | Admin, MODERATOR | Reject flagged content |
GET | /admin/zra/transmissions | Admin, FINANCE_ADMIN | ZRA transmission log |
POST | /admin/zra/retransmit/:id | Admin, FINANCE_ADMIN | Retry failed ZRA transmission |
15. Error Response Format
All errors return a consistent shape:
{
"success": false,
"error": "ORDER_NOT_FOUND",
"code": "ORDER_001",
"message": "Order not found",
"details": {
"orderId": "ord_123",
"suggestion": "Check the order ID and try again"
}
}
| HTTP Status | Meaning |
|---|---|
400 | Bad request / validation error |
401 | Unauthenticated |
402 | Payment required |
403 | Unauthorised (wrong role or MFA not verified) |
404 | Resource not found |
409 | Conflict (e.g., duplicate order) |
429 | Rate limit exceeded |
500 | Internal server error |
For internal use only. Do not distribute outside Pakashop engineering.