Afriswap exchange rates API
Integrate live bureau buy and sell rates into your app or website with a simple JSON endpoint, and receive updates automatically by webhook when rates change.
Getting a key
- Sign in (or create an account) and open My profile > API & Webhooks.
- Send an API access request. We review requests and let you know.
- Once approved, create your API key there. It is shown once, so store it safely.
Endpoint (v1.1)
GET http://www.afriswap.com/api/v1.1/
Include the trailing slash. Optional: ?currencies=USD,GBP to return only some currencies.
Authentication
| Header | Value |
|---|---|
X-API-Key | your-api-key (recommended) |
Authorization | Bearer your-api-key |
api | your-api-key (same header name as v1) |
curl -H "X-API-Key: your-api-key" http://www.afriswap.com/api/v1.1/
Successful response
{
"version": "1.1",
"base": "GHS",
"date": "2026-11-04 11:00:00",
"buy": {
"USD": "11.70",
"GBP": "15.40",
"EUR": "13.40"
},
"sell": {
"USD": "12.10",
"GBP": "16.10",
"EUR": "14.10"
}
}
- version: API version (
1.1). - base: base currency (Ghana cedi,
GHS). - date: when the rates were last published (GMT).
- buy / sell: currency codes mapped to buy and sell rates against the base.
Request limits
Each key has an hourly and a daily limit based on its plan (shown on your profile). Every response includes:
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset: this hour (reset is a Unix time).X-RateLimit-Limit-Day,X-RateLimit-Remaining-Day,X-RateLimit-Reset-Day: today (GMT).
Over the limit you get 429 Too Many Requests with a Retry-After header in seconds.
Each response has an ETag. Send it back in If-None-Match and you get an empty 304 Not Modified when rates have not changed. Better still, use a webhook instead of polling.
Errors
| Status | error | Meaning |
|---|---|---|
| 401 | missing_api_key | No key was sent. |
| 401 | invalid_api_key | Unknown, suspended or revoked key (v1 keys do not work on v1.1). |
| 429 | rate_limited | Limit reached; wait Retry-After seconds. |
| 503 | unavailable | Temporary problem; try again shortly. |
Webhooks
Add an HTTPS address on your profile and we POST the latest rates to it: as soon as rates change (within about a minute), at most every X minutes, or at set times (GMT). Only the currencies you choose are sent, and only when they changed.
{
"event": "rates.updated",
"delivery_id": 1234,
"sent_at": "2026-11-04T11:00:42Z",
"data": {
"version": "1.1",
"base": "GHS",
"date": "2026-11-04 11:00:00",
"buy": { "USD": "11.70", "GBP": "15.40" },
"sell": { "USD": "12.10", "GBP": "16.10" }
}
}
- Headers:
X-Afriswap-Event(rates.updatedortest),X-Afriswap-Delivery, andX-Afriswap-Signature: t=<unix time>,v1=<signature>. - The signature is HMAC-SHA256 of
<t>.<raw body>using your signing secret (shown on your profile). - Reply with any
2xxstatus within 5 seconds. Otherwise we retry after 1, 5, 15, 60 and 180 minutes. If newer rates are ready, we send those instead of retrying old ones. - After 20 failed attempts in a row, deliveries are paused. Fix your endpoint, then turn them back on from your profile.
Example check in PHP:
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_AFRISWAP_SIGNATURE'] ?? '';
preg_match('/t=(\d+),v1=([a-f0-9]+)/', $header, $m);
$expected = hash_hmac('sha256', $m[1] . '.' . $body, 'whsec_your_secret');
if (!$m || !hash_equals($expected, $m[2]) || abs(time() - (int) $m[1]) > 300) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
// ... save $event['data'] ...
http_response_code(200);
Legacy API (v1)
The original endpoint http://www.afriswap.com/api/ with the api header still works for existing keys,
but it is being retired. Please move to v1.1: request access from your profile, then change the URL to
http://www.afriswap.com/api/v1.1/ and use your new key. The response format is the same, plus a version field.