API Standards, Versioning & Contracts
1. REST Architecture & Resource Modeling
Debelu's backend REST API follows strict resource-oriented design principles to ensure predictable integration for web, mobile, and third-party partners.
1.1 URI & Naming Conventions
- Resource Collections: Plural nouns in kebab-case (
/api/campus-orders,/api/flash-sales,/api/vendor-applications). - Sub-Resources: Nested strictly by natural ownership:
/api/orders/:id/items/api/vendors/:id/reviews/api/campuses/:id/hubs
- Non-CRUD Actions: Expressed as explicit terminal sub-verbs:
POST /api/orders/:id/verify-deliveryPOST /api/orders/:id/cancelPOST /api/payouts/dispatch
1.2 HTTP Verbs & Semantics
| Method | Idempotent | Safe | Typical Status | Usage |
|---|---|---|---|---|
| GET | Yes | Yes | 200 OK | Resource or collection retrieval. Never mutates server state. |
| POST | No | No | 201 Created / 200 OK | Non-idempotent resource creation or state machine transition. |
| PUT | Yes | No | 200 OK | Complete resource replacement. |
| PATCH | No | No | 200 OK | Partial update of resource attributes. |
| DELETE | Yes | No | 200 OK / 204 No Content | Soft or hard deletion of an entity. |
2. Standard Envelopes & Error Contracts (RFC 7807)
2.1 Standard Success Envelope
All successful responses return JSON wrapped in a predictable meta-envelope:
{
"success": true,
"data": {
"id": "10000000-0000-4000-8000-000000000801",
"status": "Processing",
"total": 15000.00
},
"meta": {
"timestamp": "2026-10-05T09:30:00.000Z",
"version": "1.0",
"requestId": "req_a1b2c3d4e5"
}
}2.2 RFC 7807 Problem Details Specification
When an error occurs, the API returns a structured Problem Details payload in compliance with RFC 7807:
{
"type": "https://debelu.com/errors/insufficient-escrow-balance",
"title": "Insufficient Escrow Balance",
"status": 409,
"detail": "Order balance cannot be released because ₦5,000 remains unverified.",
"instance": "/api/orders/10000000-0000-4000-8000-000000000801/release",
"code": "ESCROW_BALANCE_DEFICIT",
"invalid_params": [
{
"name": "amountMinor",
"reason": "Requested amount exceeds locked escrow liability"
}
]
}2.3 Master Error Code Catalog
| Error Code | HTTP Status | Domain Category | Description |
|---|---|---|---|
AUTH_UNAUTHORIZED | 401 | Authentication | Missing or malformed Bearer token. |
AUTH_TOKEN_EXPIRED | 401 | Authentication | Supabase JWT has expired; refresh required. |
AUTH_FORBIDDEN | 403 | Authorization | Insufficient staff role or missing specific permission. |
AUTH_AAL2_REQUIRED | 403 | Authentication | Operation requires step-up Two-Factor Authentication (AAL2). |
VALIDATION_FAILED | 422 | Input Validation | Zod schema validation failed on request body or parameters. |
RESOURCE_NOT_FOUND | 404 | Data | Targeted entity does not exist or is invisible under current RLS scope. |
CONCURRENCY_CONFLICT | 409 | State Management | PostgreSQL error 40001 (Serialization Failure); stale revision supplied. |
ESCROW_LOCKED | 423 | Escrow | Funds are locked in active escrow and cannot be withdrawn. |
DELIVERY_PIN_INVALID | 400 | Fulfillment | Incorrect 4-digit Delivery PIN submitted. |
RATE_LIMIT_EXCEEDED | 429 | Traffic Control | Request quota exceeded; wait for Retry-After seconds. |
INTERNAL_ERROR | 500 | Server | Unhandled server exception; correlation ID logged to Sentry. |
3. Idempotency Standard (Idempotency-Key)
To eliminate duplicate charges and double-order submissions over unstable mobile networks:
3.1 Mandatory Endpoints
The Idempotency-Key: <UUIDv4> header is mandatory on:
POST /api/payments/intentPOST /api/orders/checkoutPOST /api/orders/:id/verify-deliveryPOST /api/payouts/dispatch
sequenceDiagram
autonumber
actor Client
participant MW as Idempotency Middleware
participant Redis as Redis Cache
participant Route as Route Handler
Client->>MW: POST /api/orders/checkout (Idempotency-Key: k_123)
MW->>Redis: SETNX lock:idemp:k_123 (TTL: 120s)
alt Lock Acquired (First Time)
MW->>Route: Execute Checkout Handler
Route-->>MW: Return HTTP 201 Created (Order Payload)
MW->>Redis: SET response:idemp:k_123 (TTL: 24h, status, body)
MW->>Redis: DEL lock:idemp:k_123
MW-->>Client: HTTP 201 Created
else Lock Held by Concurrent Request
MW-->>Client: HTTP 409 Conflict ("Operation already in progress")
else Cached Response Found
MW->>Redis: GET response:idemp:k_123
MW-->>Client: HTTP 201 Created (Cached Replay with X-Cache-Lookup: HIT)
end4. Pagination & Querying Standards
4.1 Cursor-Based Pagination (Real-Time Feeds)
Mandatory for dynamic, high-velocity feeds (product browse, chat streams, notification lists):
- Request:
GET /api/products?cursor=ZXlKMGVYQWlPaUo...&limit=20 - Response Meta:json
"meta": { "next_cursor": "ZXlKMGVYQWlPaUo...", "has_more": true, "limit": 20 }
4.2 Offset/Limit Pagination (Structured Admin/Audit)
Used strictly for deterministic, sortable tabular data:
- Request:
GET /api/payouts?page=2&limit=50&sort=created_at&order=desc - Response Meta:json
"meta": { "page": 2, "limit": 50, "total": 1240, "total_pages": 25 }
5. Rate Limiting Tiers & Header Standards
Debelu enforces dynamic rate limits via Redis sliding window counters:
| Tier | Request Quota | Scope | Target Endpoints |
|---|---|---|---|
| Tier 1: Anonymous Public | $60\text{ req/min}$ | Per IP Address | Catalog browsing, public marketing endpoints. |
| Tier 2: Authenticated Buyer | $300\text{ req/min}$ | Per User ID | Cart operations, order lookups, support tickets. |
| Tier 3: Authenticated Merchant | $600\text{ req/min}$ | Per User ID | Inventory management, product uploads, order tracking. |
| Tier 4: Sensitive Financial / Auth | $10\text{ req/min}$ | Per IP / User | Login, OTP generation, payment initialization, withdrawal. |
| Tier 5: Nduzi AI Assistant | $20\text{ req/min}$ | Per User ID | /api/gemini/stream (AI conversation). |
Standard Response Headers
Every API response transmits rate limit context:
RateLimit-Limit: 300
RateLimit-Remaining: 284
RateLimit-Reset: 1728114000When exceeded (HTTP 429):
Retry-After: 356. API Versioning, Deprecation & Sunset Policy
6.1 Versioning Conventions
- Structural breaking changes (schema removals, renamed fields) require an explicit URI version increment (
/api/v1/$\to$/api/v2/). - Non-breaking additive changes (adding optional fields, new endpoints) deploy continuously without version increments.
6.2 Formal Sunset Header Protocol
When an endpoint is marked for deprecation:
Deprecation: @1735689600
Sunset: Wed, 01 Apr 2026 00:00:00 GMT
Link: <https://debelu.com/docs/migration/v2>; rel="sunset"The platform guarantees a minimum 6-month support window between formal deprecation notice and physical endpoint decommission.