GetDataGH API
Sell data bundles directly from your app or website.
With a few API calls, your customers can browse data packages, pay via mobile money or card, and receive their data automatically. No manual processing needed.
Base URL (use this for all requests)
https://www.getdatagh.com/api/v1Important: Always use www. in the URL. Requests to the non-www domain will be redirected and may fail.
Protocol
HTTPSResponse Format
JSONCurrency
GHS (Ghana Cedi)Get started in 4 steps
Create an account
Sign up hereSet your prices
Pricing dashboardGenerate an API key
Go to SettingsMake your first API call
See examples belowTry it now — paste this in your terminal to test your key:
curl -X GET "https://www.getdatagh.com/api/v1/packages" \
-H "Authorization: Bearer gdgh_your_api_key_here"Authentication
Every API request needs your API key. Include it in the Authorization header like this:
Authorization: Bearer gdgh_your_api_key_hereWhat does an API key look like?
Your API key starts with gdgh_ followed by 40 characters (letters and numbers). For example: gdgh_a1b2c3d4e5f6.... We never store your raw key — treat it like a password.
| Property | Value |
|---|---|
| Prefix | gdgh_ |
| Length | 45 characters total |
| Format | gdgh_ + 40 hex characters |
| Storage | SHA-256 hashed (irreversible) |
How to get your API Key
- Go to Dashboard → Settings
- Click the "Generate API Key" button
- Copy the key immediately — you will only see it once
- Save it somewhere safe (like an environment variable on your server)
Keep your API key safe
- Never put your API key in client-side code (HTML, JavaScript in the browser, mobile apps)
- Always make API calls from your backend server
- Store keys in environment variables, not in your source code
- If you think your key has been leaked, revoke it and create a new one right away
CORS
The API allows requests from any origin. All endpoints respond to OPTIONS preflight requests.
| Header | Value |
|---|---|
| Access-Control-Allow-Origin | * |
| Access-Control-Allow-Methods | GET, POST, OPTIONS |
| Access-Control-Allow-Headers | Authorization, Content-Type |
Rate Limits
To keep things running smoothly for everyone, there are limits on how many requests you can make per minute.
| Tier | Limit | Window |
|---|---|---|
| Standard | 100 requests | Per minute |
| Purchase endpoint | 20 requests | Per minute |
429 Too Many Requests response. Just wait a moment and try again. Need higher limits? Contact support.List Packages
/api/v1/packagesGet a list of all the data bundles you can sell, along with their prices. This is usually the first call you make — use it to show your customers what's available.
You can filter by network (MTN, TELECEL, or AIRTELTIGO) to only show packages for a specific provider.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| network | string | Optional | Filter by network: MTN, TELECEL, or AIRTELTIGO |
Request
curl -X GET "https://www.getdatagh.com/api/v1/packages?network=MTN" \
-H "Authorization: Bearer gdgh_your_api_key_here"Response
{
"vendor": {
"code": "ABC123",
"name": "John's Data Shop"
},
"packages": [
{
"package_code": "MTN-1GB",
"name": "MTN 1GB Bundle",
"network": "MTN",
"data_quantity": 1,
"data_unit": "GB",
"price": 5.00
},
{
"package_code": "MTN-2GB",
"name": "MTN 2GB Bundle",
"network": "MTN",
"data_quantity": 2,
"data_unit": "GB",
"price": 9.50
}
]
}Response Fields
| Field | Type | Description |
|---|---|---|
| vendor.code | string | Your unique vendor code |
| vendor.name | string | Your registered business name |
| packages[].package_code | string | Unique package identifier — use this when making a purchase |
| packages[].name | string | Human-readable package name |
| packages[].network | string | Mobile network (MTN, TELECEL, AIRTELTIGO) |
| packages[].data_quantity | number | Amount of data included |
| packages[].data_unit | string | Unit of data (MB or GB) |
| packages[].price | number | Your selling price in GHS |
Initiate Purchase
/api/v1/purchaseStart a data bundle purchase for your customer. This gives you a payment link — send your customer there to pay via mobile money or card.
Once they pay, the data bundle is delivered to the phone number automatically. No extra steps needed from your side.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| package_code | string | Required | Package identifier from /packages |
| phone_number | string | Required | Recipient's phone number (e.g., 0241234567) |
| network | string | Required | MTN, TELECEL, or AIRTELTIGO |
| string | Optional | Customer's email for payment receipt from Paystack | |
| callback_url | string | Optional | URL to redirect customer to after payment completes |
Request
curl -X POST "https://www.getdatagh.com/api/v1/purchase" \
-H "Authorization: Bearer gdgh_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"package_code": "MTN-1GB",
"phone_number": "0241234567",
"network": "MTN",
"email": "customer@example.com",
"callback_url": "https://yoursite.com/payment-complete"
}'Response
{
"success": true,
"transaction_ref": "GD8A3F1B2C",
"payment_url": "https://checkout.paystack.com/xyz123abc",
"amount": 5.10,
"currency": "GHS"
}Response Fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the purchase was initiated successfully |
| transaction_ref | string | Unique transaction reference (starts with GD). Save this to track the order. |
| payment_url | string | Paystack checkout URL — send your customer here to pay |
| amount | number | Total amount to be charged in GHS (includes processing fees) |
| currency | string | Always GHS |
Good to know
- The amount may be slightly higher than the package price due to a small processing fee.
- Each payment link can only be used once and expires if not used.
- Data delivery happens automatically after payment — you don't need to do anything else.
Error Responses
| Status | Code | When |
|---|---|---|
| 400 | INVALID_BODY | Request body is not valid JSON |
| 400 | MISSING_FIELDS | package_code, phone_number, or network is missing |
| 400 | INVALID_PACKAGE | Package code not found or package is inactive |
| 400 | NO_PRICE | You haven't set a price for this package yet |
| 400 | PAYMENT_FAILED | Paystack could not initialize the payment |
Get Transaction
/api/v1/transactions/:refCheck what happened with a specific purchase. Use the transaction reference you got when you initiated the purchase.
This tells you if the customer paid, and whether the data was delivered to their phone.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| :ref | string | Required | Transaction reference from POST /purchase (e.g., GD8A3F1B2C) |
Request
curl -X GET "https://www.getdatagh.com/api/v1/transactions/GD8A3F1B2C" \
-H "Authorization: Bearer gdgh_your_api_key_here"Response
{
"transaction_ref": "GD8A3F1B2C",
"status": "SUCCESS",
"data_transfer_status": "SENT",
"package_code": "MTN-1GB",
"network": "MTN",
"recipient_number": "0241234567",
"amount": 5.00,
"created_at": "2026-03-29T15:00:00.000Z"
}Response Fields
| Field | Type | Description |
|---|---|---|
| transaction_ref | string | Unique transaction reference |
| status | string | Payment status (see table below) |
| data_transfer_status | string | Data delivery status (see table below) |
| package_code | string | The package that was purchased |
| network | string | Mobile network of the recipient |
| recipient_number | string | Phone number that received the data |
| amount | number | Amount charged in GHS |
| created_at | string | When the transaction was created (ISO 8601) |
Payment Status
| Status | What it means |
|---|---|
| INITIATED | Payment link created, waiting for customer to pay |
| PENDING | Payment is being processed |
| SUCCESS | Customer paid successfully |
| FAILED | Payment failed or was declined |
Data Transfer Status
| Status | What it means |
|---|---|
| PENDING | Data has not been sent yet |
| SENT | Data bundle delivered to recipient |
| FAILED | Data delivery failed — contact support |
Get Balance
/api/v1/balanceSee how much you've earned. Returns your total sales, commission earned, amount already paid out, and what's still pending.
Request
curl -X GET "https://www.getdatagh.com/api/v1/balance" \
-H "Authorization: Bearer gdgh_your_api_key_here"Response
{
"total_sales": 1500.00,
"total_commission": 150.00,
"total_paid_out": 50.00,
"pending_payout": 100.00,
"total_transactions": 300,
"successful_transactions": 285
}Response Fields
| Field | Type | Description |
|---|---|---|
| total_sales | number | Total revenue from all successful transactions (GHS) |
| total_commission | number | Total commission earned (GHS) |
| total_paid_out | number | Amount already paid out to you (GHS) |
| pending_payout | number | Commission earned but not yet paid out (GHS) |
| total_transactions | number | Total number of transactions created |
| successful_transactions | number | Transactions where payment was successful |
Error Handling
When something goes wrong, the API returns a clear error message telling you what happened and how to fix it.
Status codes starting with 2xx mean success, 4xx means something in your request needs fixing, and 5xx means something went wrong on our end.
Error Response Format
Every error has a machine-readable code (for your code to check) and a human-readable message (to help you debug).
{
"error": {
"message": "A human-readable description of the error",
"code": "MACHINE_READABLE_CODE"
}
}Error Code Reference
| HTTP Status | Code | Description | What to do |
|---|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key | Check your Authorization header and key format. Make sure you're using the www. URL. |
| 403 | FORBIDDEN | Vendor account inactive | Contact support to reactivate your account |
| 400 | INVALID_BODY | Malformed JSON in request body | Check that Content-Type is application/json and body is valid JSON |
| 400 | MISSING_FIELDS | Required fields not provided | Include package_code, phone_number, and network |
| 400 | INVALID_PACKAGE | Package code not found or inactive | Double-check the package_code from GET /packages |
| 400 | NO_PRICE | No price configured for this package | Set a price for this package in your dashboard |
| 400 | PAYMENT_FAILED | Payment gateway initialization failed | Try again. If it keeps happening, contact support. |
| 404 | NOT_FOUND | Transaction reference not found | Check the reference and make sure it belongs to your account |
| 429 | RATE_LIMITED | Too many requests | Wait a moment, then try again |
| 500 | INTERNAL_ERROR | Server error | Try again. Contact support if it persists. |
Handling Errors in Code
const response = await fetch(`${BASE}/purchase`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(purchaseData),
});
if (!response.ok) {
const { error } = await response.json();
switch (error.code) {
case "UNAUTHORIZED":
// Check your API key
break;
case "MISSING_FIELDS":
// Show validation errors to user
break;
case "INVALID_PACKAGE":
// Refresh package list
break;
case "NO_PRICE":
// Package exists but you haven't set a price
break;
case "PAYMENT_FAILED":
// Retry or show payment error
break;
default:
console.error(`API Error [${error.code}]: ${error.message}`);
}
return;
}
const data = await response.json();
// Handle success...Webhooks
Want to know when a customer finishes paying? When you create a purchase, include a callback_url. After payment, the customer gets sent back to your site with the transaction reference, so you can look up what happened.
Callback Flow
https://yoursite.com/payment-complete?reference=GD8A3F1B2C// Example: Next.js page handling the callback
// app/payment-complete/page.tsx
export default async function PaymentComplete({ searchParams }) {
const ref = searchParams.reference;
// Verify the transaction status server-side
const response = await fetch(
`https://www.getdatagh.com/api/v1/transactions/${ref}`,
{ headers: { Authorization: `Bearer ${process.env.GDGH_API_KEY}` } }
);
const transaction = await response.json();
if (transaction.status === "SUCCESS") {
// Show success page
} else {
// Show pending/failed page
}
}Always verify server-side
GET /transactions/:ref from your server to confirm the payment actually went through before showing a success message.Code Examples
Copy-paste ready code in your language. Each example shows you how to list packages, make a purchase, and check transaction status — everything you need to get started.
JavaScript / Node.js
const API_KEY = process.env.GDGH_API_KEY;
const BASE = "https://www.getdatagh.com/api/v1";
const headers = {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
};
// ── List all MTN packages ──────────────────────
async function listPackages(network) {
const url = new URL(`${BASE}/packages`);
if (network) url.searchParams.set("network", network);
const res = await fetch(url, { headers });
if (!res.ok) throw new Error(`Failed to list packages: ${res.status}`);
return res.json();
}
// ── Initiate a purchase ────────────────────────
async function purchase({ packageCode, phoneNumber, network, email, callbackUrl }) {
const res = await fetch(`${BASE}/purchase`, {
method: "POST",
headers,
body: JSON.stringify({
package_code: packageCode,
phone_number: phoneNumber,
network,
email,
callback_url: callbackUrl,
}),
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(`Purchase failed [${error.code}]: ${error.message}`);
}
return res.json();
}
// ── Check transaction status ───────────────────
async function getTransaction(ref) {
const res = await fetch(`${BASE}/transactions/${ref}`, { headers });
if (!res.ok) throw new Error(`Transaction not found: ${ref}`);
return res.json();
}
// ── Check balance ──────────────────────────────
async function getBalance() {
const res = await fetch(`${BASE}/balance`, { headers });
if (!res.ok) throw new Error("Failed to fetch balance");
return res.json();
}
// ── Usage ──────────────────────────────────────
async function main() {
// 1. List MTN packages
const { packages } = await listPackages("MTN");
console.log("Available packages:", packages);
// 2. Purchase first package
const result = await purchase({
packageCode: packages[0].package_code,
phoneNumber: "0241234567",
network: "MTN",
email: "customer@example.com",
callbackUrl: "https://yoursite.com/success",
});
console.log("Payment URL:", result.payment_url);
// 3. Check status (after customer pays)
const tx = await getTransaction(result.transaction_ref);
console.log("Status:", tx.status, "| Delivery:", tx.data_transfer_status);
// 4. Check balance
const balance = await getBalance();
console.log("Pending payout:", balance.pending_payout, "GHS");
}
main().catch(console.error);Python
import os
import requests
API_KEY = os.environ["GDGH_API_KEY"]
BASE = "https://www.getdatagh.com/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def list_packages(network: str | None = None) -> dict:
"""List available data packages, optionally filtered by network."""
params = {"network": network} if network else {}
response = requests.get(f"{BASE}/packages", headers=HEADERS, params=params)
response.raise_for_status()
return response.json()
def purchase(
package_code: str,
phone_number: str,
network: str,
email: str | None = None,
callback_url: str | None = None,
) -> dict:
"""Initiate a data bundle purchase."""
payload = {
"package_code": package_code,
"phone_number": phone_number,
"network": network,
}
if email:
payload["email"] = email
if callback_url:
payload["callback_url"] = callback_url
response = requests.post(f"{BASE}/purchase", headers=HEADERS, json=payload)
response.raise_for_status()
return response.json()
def get_transaction(ref: str) -> dict:
"""Check the status of a transaction."""
response = requests.get(f"{BASE}/transactions/{ref}", headers=HEADERS)
response.raise_for_status()
return response.json()
def get_balance() -> dict:
"""Get your commission balance summary."""
response = requests.get(f"{BASE}/balance", headers=HEADERS)
response.raise_for_status()
return response.json()
# ── Usage ──────────────────────────────────────────
if __name__ == "__main__":
# 1. List MTN packages
data = list_packages("MTN")
print(f"Found {len(data['packages'])} MTN packages")
# 2. Initiate a purchase
result = purchase(
package_code="MTN-1GB",
phone_number="0241234567",
network="MTN",
email="customer@example.com",
callback_url="https://yoursite.com/success",
)
print(f"Payment URL: {result['payment_url']}")
# 3. Check transaction status
tx = get_transaction(result["transaction_ref"])
print(f"Status: {tx['status']} | Delivery: {tx['data_transfer_status']}")
# 4. Check balance
balance = get_balance()
print(f"Pending payout: GHS {balance['pending_payout']}")PHP
<?php
class GetDataGH
{
private string $apiKey;
private string $baseUrl = "https://www.getdatagh.com/api/v1";
public function __construct(string $apiKey)
{
$this->apiKey = $apiKey;
}
/**
* List available data packages.
*/
public function listPackages(?string $network = null): array
{
$url = $this->baseUrl . "/packages";
if ($network) {
$url .= "?network=" . urlencode($network);
}
return $this->request("GET", $url);
}
/**
* Initiate a data bundle purchase.
*/
public function purchase(array $data): array
{
return $this->request("POST", $this->baseUrl . "/purchase", $data);
}
/**
* Check transaction status by reference.
*/
public function getTransaction(string $ref): array
{
return $this->request("GET", $this->baseUrl . "/transactions/" . $ref);
}
/**
* Get your commission balance summary.
*/
public function getBalance(): array
{
return $this->request("GET", $this->baseUrl . "/balance");
}
private function request(string $method, string $url, ?array $body = null): array
{
$ch = curl_init($url);
$headers = [
"Authorization: Bearer " . $this->apiKey,
"Content-Type: application/json",
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if ($method === "POST" && $body) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
}
$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($statusCode >= 400) {
throw new Exception(
"API Error [{$data['error']['code']}]: {$data['error']['message']}"
);
}
return $data;
}
}
// ── Usage ──────────────────────────────────────────
$api = new GetDataGH(getenv("GDGH_API_KEY"));
// 1. List MTN packages
$packages = $api->listPackages("MTN");
echo "Found " . count($packages["packages"]) . " MTN packages\n";
// 2. Initiate a purchase
$result = $api->purchase([
"package_code" => "MTN-1GB",
"phone_number" => "0241234567",
"network" => "MTN",
"email" => "customer@example.com",
"callback_url" => "https://yoursite.com/success",
]);
echo "Payment URL: " . $result["payment_url"] . "\n";
// 3. Redirect customer to payment
header("Location: " . $result["payment_url"]);cURL
# Set your API key
export GDGH_KEY="gdgh_your_api_key_here"
# ── List all packages ──────────────────────────
curl -s -H "Authorization: Bearer $GDGH_KEY" \
"https://www.getdatagh.com/api/v1/packages" | jq .
# ── List MTN packages only ─────────────────────
curl -s -H "Authorization: Bearer $GDGH_KEY" \
"https://www.getdatagh.com/api/v1/packages?network=MTN" | jq .
# ── Initiate a purchase ───────────────────────
curl -s -X POST "https://www.getdatagh.com/api/v1/purchase" \
-H "Authorization: Bearer $GDGH_KEY" \
-H "Content-Type: application/json" \
-d '{
"package_code": "MTN-1GB",
"phone_number": "0241234567",
"network": "MTN",
"email": "customer@example.com",
"callback_url": "https://yoursite.com/success"
}' | jq .
# ── Check a transaction ───────────────────────
curl -s -H "Authorization: Bearer $GDGH_KEY" \
"https://www.getdatagh.com/api/v1/transactions/GD8A3F1B2C" | jq .
# ── Check your balance ────────────────────────
curl -s -H "Authorization: Bearer $GDGH_KEY" \
"https://www.getdatagh.com/api/v1/balance" | jq .Integration Flow
Here's the full picture of how a purchase works, from start to finish. Follow these steps to integrate GetDataGH into your app.
Show packages on your site
Call GET /packages to get available data bundles with your prices. Let customers pick what they want.
GET /api/v1/packages?network=MTNCollect customer details
Get the recipient's phone number and network. Optionally collect their email for a payment receipt.
Create the purchase (from your server)
Send a POST request to /purchase with the package code, phone number, and network. Always do this from your backend to keep your API key safe.
POST /api/v1/purchase
{ "package_code": "MTN-1GB", "phone_number": "0241234567", "network": "MTN" }Send customer to pay
Redirect the customer to the payment_url from the response. They'll see a Paystack checkout page where they can pay with mobile money or card.
// Redirect
window.location.href = response.payment_url;Customer pays, data is sent
After payment, the customer is redirected to your callback_url (if you set one). The data bundle is automatically delivered to the phone number.
GET https://yoursite.com/success?reference=GD8A3F1B2CVerify and show confirmation
On your callback page, check the transaction status to confirm everything went through, then show the customer a confirmation.
GET /api/v1/transactions/GD8A3F1B2C
→ { "status": "SUCCESS", "data_transfer_status": "SENT" }That's it!
Changelog
Initial Release — March 2026
- List packages with network filtering
- Initiate purchases with Paystack payment
- Transaction status tracking
- Commission balance endpoint
- API key authentication
Stuck or need help? We're happy to assist.
Email support@getdatagh.comGetDataGH · API v1 · Last updated April 2026