API Documentation
Use this documentation to connect to the Citrusrate API and WebSocket streams.
Getting Started
Citrusrate V1 API Documentation
Welcome to the Citrusrate V1 API. This API provides real-time and black-market exchange rates for Bitcoin (BTC) and Fiat currencies across Africa.
Base URL
Authentication
All requests to the V1 API must use an API key. Put your API key in the X-API-Key header of every request.
To get an API key, buy a developer plan. View the plans on the Developer Plans page.
Example Request:
curl -H "X-API-Key: your_api_key_here" \ "https://api.citrusrate.com/v1/btc?currency=NGN"
Supported Currencies (African Fiat)
Citrusrate currently supports 41 African currencies. Use these tickers in the currency query parameter for any endpoint.
| Ticker | Currency Name | Ticker | Currency Name |
|---|---|---|---|
| AOA | Angolan Kwanza | MAD | Moroccan Dirham |
| BIF | Burundian Franc | MGA | Malagasy Ariary |
| BWP | Botswana Pula | MRO | Mauritanian Ouguiya |
| CVE | Cape Verdean Escudo | MUR | Mauritian Rupee |
| CDF | Congolese Franc | MWK | Malawian Kwacha |
| DJF | Djiboutian Franc | MZN | Mozambican Metical |
| DZD | Algerian Dinar | NAD | Namibian Dollar |
| ERN | Eritrean Nakfa | NGN | Nigerian Naira |
| ETB | Ethiopian Birr | RWF | Rwandan Franc |
| GHS | Ghanaian Cedi | SCR | Seychellois Rupee |
| GMD | Gambian Dalasi | GNF | Guinean Franc |
| KES | Kenyan Shilling | LRD | Liberian Dollar |
| KMF | Comorian Franc | LSL | Lesotho Loti |
| LYD | Libyan Dinar | SDG | Sudanese Pound |
| SLL | Sierra Leonean Leone | SOS | Somali Shilling |
| SSP | South Sudanese Pound | STN | São Tomé Dobra |
| SZL | Eswatini Lilangeni | TND | Tunisian Dinar |
| TZS | Tanzanian Shilling | UGX | Ugandan Shilling |
| XAF | Central African CFA Franc | XOF | West African CFA Franc |
| ZAR | South African Rand | ZMW | Zambian Kwacha |
| ZWD | Zimbabwean Dollar |
Supported Black Market Currencies
We provide parallel market and peer-to-peer (P2P) rate data for these 13 currencies:
| Ticker | Currency Name | Ticker | Currency Name |
|---|---|---|---|
| EGP | Egyptian Pound | ETB | Ethiopian Birr |
| GHS | Ghanaian Cedi | MWK | Malawian Kwacha |
| MZN | Mozambican Metical | NAD | Namibian Dollar |
| RWF | Rwandan Franc | TZS | Tanzanian Shilling |
| UGX | Ugandan Shilling | XAF | Central African CFA Franc |
| XOF | West African CFA Franc | ZAR | South African Rand |
| ZMW | Zambian Kwacha |
L402 Lightning Auth
If you do not have an API key, you can use the L402 protocol. If you send a request without a key, the server returns an HTTP 402 error. This error contains a Lightning invoice.
Pay the invoice with a Lightning wallet to get a Macaroon token. This token grants you 10 minutes of access to the endpoint. Put this token in the Authorization header to complete your requests. Standard API rate limits apply during this 10-minute window.
This is an example of the HTTP 402 (Payment Required) response:
{
"status": "payment_required",
"message": "Payment of 500 sats required to access this endpoint.",
"payment": {
"macaroon": "ASI2yzTmASi5b5...",
"invoice": "lnbc500n1p4xp5y9p...",
"paymentHash": "2236cb34e6...",
"amount": 500,
"currency": "SAT",
"expiresAt": "2026-07-22T14:27:05.000Z"
},
"service": {
"name": "Citrusrate",
"description": "Real-time FX rates for African currencies",
"endpoint": "/v1/fiat/mid?currency=MWK"
}
}WebSocket Streaming
Citrusrate sends real-time data with Socket.IO for premium plans. Use a standard Socket.IO client to connect. Put your API key in the auth object.
1. Real-Time Prices Stream
This stream sends all official African exchange rates every 3 seconds. Namespace: /ws/developer/prices
import { io } from "socket.io-client"; const socket = io("wss://api.citrusrate.com/ws/developer/prices", { auth: { apiKey: "your_api_key_here" } }); socket.on("connect", () => console.log("Connected!")); socket.on("data", (prices) => { console.log("Live Prices:", prices); });
2. Black Market Rates Stream
This stream sends live peer-to-peer (P2P) and parallel market data every 5 seconds. Namespace: /ws/developer/blackmarket
import { io } from "socket.io-client"; const socket = io("wss://api.citrusrate.com/ws/developer/blackmarket", { auth: { apiKey: "your_api_key_here", currencies: ["NGN", "GHS", "KES"] // Max Tier only } }); socket.on("data", (rates) => { console.log("Black Market Rates:", rates); });
Business plan: You do not need to send the currencies list to get all rates.
Best Practices
- Caching: Cache the rate data on your side for at least 30 to 60 seconds to get better performance.
- Handling 429s: If you receive an HTTP 429 error, read the
retryAfterfield (in seconds) before you send a new request. - Timeouts: Make sure that your client handles network timeouts correctly. We recommend a timeout of 5 to 10 seconds.
Error Codes
The API uses standard HTTP status codes to show if a request is successful or has an error. These are the common error codes:
| Code | Meaning | Description |
|---|---|---|
| 400 | Bad Request | Missing or invalid parameters. |
| 401 | Unauthorized | API key is missing, invalid, or revoked. |
| 403 | Forbidden | Your API key does not have the required scope. |
| 429 | Too Many Requests | You have exceeded your rate limit. |
| 500 | Server Error | Internal issue; please contact support. |
Get Official Single Price
Get the current Bitcoin (BTC) exchange rate against a specific fiat currency.
Parameters
| Name | Type | Description |
|---|---|---|
| currency* | string | The currency ticker (e.g. NGN). |
curl -X GET "https://api.citrusrate.com/v1/btc?currency=NGN" \ -H "X-API-Key: YOUR_API_KEY"
Headers
| Name | Type | Description |
|---|---|---|
| X-API-Key | string | Your Citrusrate API key used to authorize the request. |
Response Fields
| Field | Type | Description |
|---|---|---|
| status | string | Overall result of the request, e.g. success. |
| data.pair | string | Currency pair quoted, here BTC/NGN. |
| data.rate | number | Current exchange rate for 1 BTC in NGN. |
| data.timestamp | string (ISO 8601) | Time the rate was generated. |
Get Official Batch Price
Returns the current BTC exchange rates in up to five multiple African fiat currencies.
Parameters
| Name | Type | Description |
|---|---|---|
| currencies* | string | Comma-separated list of fiat currency codes (max 5), e.g. NGN,GHS,XOF,ZAR,KES |
curl -X GET "https://api.citrusrate.com/v1/btc/batch?currencies=NGN,GHS,XOF,ZAR,KES" \ -H "X-API-Key: YOUR_API_KEY"
Headers
| Name | Type | Description |
|---|---|---|
| X-API-Key | string | Your Citrusrate API key used to authorize the request. |
Response Fields
| Field | Type | Description |
|---|---|---|
| status | string | High-level status of the request (e.g. success). |
| data | object | Map of currency code to rate information. |
| data.<CURRENCY> | object | Key for each requested fiat currency (e.g. NGN, GHS, XOF, ZAR, KES). |
| data.<CURRENCY>.rate | number | Current BTC price denominated in that fiat currency. |
| data.<CURRENCY>.timestamp | string (ISO 8601) | ISO-8601 timestamp indicating when the rate was last updated. |
BTC All Fiat Rates
Retrieve the latest BTC conversion rates against all supported fiat currencies.
curl -X GET "https://api.citrusrate.com/v1/btc/all" \ -H "X-API-Key: YOUR_API_KEY"
Headers
| Name | Type | Description |
|---|---|---|
| X-API-Key | string | Your Citrusrate API key used to authorize the request. |
Response Fields
| Field | Type | Description |
|---|---|---|
| status | string | String flag indicating request outcome (e.g. success). |
| data | object | Object wrapping the payload. |
| data.rates | object | Object where each key is a 3-letter fiat currency code and the value is the rate of 1 BTC in that currency. |
| data.timestamp | string (ISO 8601) | ISO-8601 timestamp string indicating when the rates snapshot was generated. |
Get Black Market Single Rate
Retrieve the current black-market Bitcoin (BTC) exchange rate for a specific fiat currency.
Parameters
| Name | Type | Description |
|---|---|---|
| currency* | string | ISO currency code of the fiat currency, e.g. MZN |
curl -X GET "https://api.citrusrate.com/v1/btc/blackmarket?currency=MZN" \ -H "X-API-Key: YOUR_API_KEY"
Headers
| Name | Type | Description |
|---|---|---|
| X-API-Key | string | Your Citrusrate API key used to authorize the request. |
| Content-Type | string | Must be set to application/json |
Response Fields
| Field | Type | Description |
|---|---|---|
| status | string | High-level status of the request (e.g., success). |
| data.pair | string | Currency pair quoted, here BTC/MZN. |
| data.rate | number | Current estimated BTC price denominated in Mozambican Metical (MZN). |
| data.timestamp | string (ISO 8601) | ISO-8601 timestamp indicating when the rate was last updated. |
| data.source | string | Rate generation methodology (e.g. live). |
Get Black Market All Rates
Retrieve the current black-market Bitcoin (BTC) exchange rate for all supported currencies.
curl -X GET "https://api.citrusrate.com/v1/btc/blackmarket/all" \ -H "X-API-Key: YOUR_API_KEY"
Headers
| Name | Type | Description |
|---|---|---|
| X-API-Key | string | Your Citrusrate API key used to authorize the request. |
| Content-Type | string | Must be set to application/json |
Response Fields
| Field | Type | Description |
|---|---|---|
| status | string | High-level status of the request (e.g. success). |
| data.rates | object | Map of currency codes to rate objects. |
| data.rates.<CURRENCY>.rate | number | Black-market exchange rate of BTC in that currency. |
| data.timestamp | string (ISO 8601) | ISO-8601 timestamp string indicating when the snapshot was generated. |