This document describes the standard response format and handling rules for the API. It explains how to interpret HTTP and business status codes, how to reliably process responses, and how to implement robust client handling logic. It also provides code examples for common programming languages.
Got it — here’s the tightened, client‑friendly version of your live API documentation. HTTP 401, 403, and 500 are the only non‑200 statuses you will encounter, so clients should not expect other HTTP error codes. All business errors are always returned with HTTP 200 to clearly distinguish them from transport-level errors.
Summary of Supported HTTP Status Codes
| HTTP Status | Meaning | Typical Cause | Suggested Client Action |
|---|---|---|---|
| 200 | OK | Request processed successfully; check statusCode for business outcome | Use data if statusCode = "00"; otherwise follow business error guidance |
| 401 | Unauthorized | Missing or invalid authentication | Re-authenticate and retry |
| 403 | Forbidden | Authenticated but not permitted to access the resource | Check permissions or contact support |
| 500 | Internal Server Error | Unexpected backend failure | Retry with exponential backoff |
Note: Non-200 responses (401, 403, 500) may not always include the standard JSON body. Business errors will always be returned with HTTP 200 and the standard JSON structure.
API Response Contract & Handling Guide
Standard Response Format
{
"data": {
"balance": 3470577.33,
"currency": "NGN"
},
"statusCode": "00",
"message": "Successful"
}
Contract: All endpoints return data, statusCode, and message. Always check statusCode to determine the business outcome ("00" = success`). HTTP status codes indicate the transport-level result (e.g., request/connection/auth). Business status codes inside the body indicate the application-level outcome.
Versioning Note: This format is part of the stable API contract and will remain unchanged for all v1.x releases. Any breaking change will occur only in a major version (v2, v3, …) and will be announced in documentation. Clients should parse defensively to handle additive fields.
Quick Start
Test Call (curl)
curl -X GET "https://api.example.com/v1/wallet/balance" \
-H "Authorization: Bearer <token>"
Successful Response
{
"data": { "balance": 3470577.33, "currency": "NGN" },
"statusCode": "00",
"message": "Successful"
}
Business Error Response
{
"data": null,
"statusCode": "02",
"message": "Insufficient wallet balance"
}
Field Semantics
data— Object ornull.statusCode— String business code.message— Human‑readable description.
Handling Logic
if (HTTP status is 200) {
if (statusCode == "00") use data
else handle business error
} else {
handle transport error
}
Business Error Codes
| Code | Message | Guidance |
|---|---|---|
| 00 | OK | Success; use data. |
| 01 | Invalid request | Fix request and retry. |
| 02 | Insufficient Wallet balance | Top up or reduce amount. |
| 04 | Duplicate reference | Use unique reference. |
| 10 | Invalid amount | Adjust and retry. |
| 24 | Server error | Retry with backoff. |
| 27 | Product not found | Verify ID/code. |
| 28 | Product not available | Out of stock/unavailable. |
| 40 | Order not found | Check identifiers. |
Reliability & Retries
- Use exponential backoff for HTTP 500.
- Don’t auto‑retry business errors unless fixable.
- Always log
statusCodeandmessage.
Client Example (JavaScript - fetch)
async function callApi(url) {
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const body = await res.json();
if (body.statusCode === '00') return body.data;
throw new Error(`${body.statusCode}: ${body.message}`);
}
Client Example (Axios)
import axios from 'axios';
const api = axios.create({ baseURL: 'https://api.example.com', timeout: 15000 });
api.interceptors.response.use(
(response) => {
const body = response.data;
if (body?.statusCode === '00') return body.data;
const err = new Error(`${body?.statusCode}: ${body?.message}`);
err.code = body?.statusCode;
return Promise.reject(err);
},
(error) => {
if (error.response) {
return Promise.reject(new Error(`HTTP ${error.response.status}`));
}
return Promise.reject(error);
}
);
export default api;
Client Example (Python - requests)
import requests
class TransportError(Exception):
pass
class BusinessError(Exception):
def __init__(self, code, message):
super().__init__(f"{code}: {message}")
self.code = code
self.message = message
def call_api(url, method='GET', **kwargs):
resp = requests.request(method, url, timeout=15, **kwargs)
if not (200 <= resp.status_code < 300):
raise TransportError(f"HTTP {resp.status_code}")
body = resp.json()
if body.get('statusCode') == '00':
return body.get('data')
raise BusinessError(body.get('statusCode'), body.get('message'))
How to Debug Failures
- Check HTTP status code.
- If HTTP is 200, check
statusCode. - Log
statusCode,message, and request reference ID. - For business errors, follow the “Guidance” column.
- For HTTP 500, apply exponential backoff.
FAQ
Q: Why is HTTP 200 but statusCode != "00"?
A: Business logic failed; check statusCode for the reason.
Q: Should I retry all failures?
A: Only retry HTTP 500 and fixable business errors per table.
Q: Will this format change?
A: Not in v1.x. Any breaking change will be announced in a new major version.
This version is safe for clients, matches the live API exactly, and reflects only the supported HTTP status codes.