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/v1

Important: Always use www. in the URL. Requests to the non-www domain will be redirected and may fail.

Protocol

HTTPS

Response Format

JSON

Currency

GHS (Ghana Cedi)

Get started in 4 steps

1

Create an account

Sign up here
2

Set your prices

Pricing dashboard
3

Generate an API key

Go to Settings
4

Make your first API call

See examples below

Try it now — paste this in your terminal to test your key:

Quick test — list your packagesbash
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:

Add this header to every request
Authorization: Bearer gdgh_your_api_key_here

What 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.

PropertyValue
Prefixgdgh_
Length45 characters total
Formatgdgh_ + 40 hex characters
StorageSHA-256 hashed (irreversible)

How to get your API Key

  1. Go to Dashboard → Settings
  2. Click the "Generate API Key" button
  3. Copy the key immediately — you will only see it once
  4. 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.

HeaderValue
Access-Control-Allow-Origin*
Access-Control-Allow-MethodsGET, POST, OPTIONS
Access-Control-Allow-HeadersAuthorization, Content-Type

Rate Limits

To keep things running smoothly for everyone, there are limits on how many requests you can make per minute.

TierLimitWindow
Standard100 requestsPer minute
Purchase endpoint20 requestsPer minute
i
If you go over the limit, you'll get a 429 Too Many Requests response. Just wait a moment and try again. Need higher limits? Contact support.

List Packages

GET/api/v1/packages

Get 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

ParameterTypeRequiredDescription
networkstringOptionalFilter by network: MTN, TELECEL, or AIRTELTIGO

Request

cURLbash
curl -X GET "https://www.getdatagh.com/api/v1/packages?network=MTN" \
  -H "Authorization: Bearer gdgh_your_api_key_here"

Response

200 OKjson
{
  "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

FieldTypeDescription
vendor.codestringYour unique vendor code
vendor.namestringYour registered business name
packages[].package_codestringUnique package identifier — use this when making a purchase
packages[].namestringHuman-readable package name
packages[].networkstringMobile network (MTN, TELECEL, AIRTELTIGO)
packages[].data_quantitynumberAmount of data included
packages[].data_unitstringUnit of data (MB or GB)
packages[].pricenumberYour selling price in GHS
i
Only packages you have set prices for will show up. Head to the pricing dashboard to configure your prices.

Initiate Purchase

POST/api/v1/purchase

Start 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

FieldTypeRequiredDescription
package_codestringRequiredPackage identifier from /packages
phone_numberstringRequiredRecipient's phone number (e.g., 0241234567)
networkstringRequiredMTN, TELECEL, or AIRTELTIGO
emailstringOptionalCustomer's email for payment receipt from Paystack
callback_urlstringOptionalURL to redirect customer to after payment completes

Request

cURLbash
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

200 OKjson
{
  "success": true,
  "transaction_ref": "GD8A3F1B2C",
  "payment_url": "https://checkout.paystack.com/xyz123abc",
  "amount": 5.10,
  "currency": "GHS"
}

Response Fields

FieldTypeDescription
successbooleanWhether the purchase was initiated successfully
transaction_refstringUnique transaction reference (starts with GD). Save this to track the order.
payment_urlstringPaystack checkout URL — send your customer here to pay
amountnumberTotal amount to be charged in GHS (includes processing fees)
currencystringAlways 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

StatusCodeWhen
400INVALID_BODYRequest body is not valid JSON
400MISSING_FIELDSpackage_code, phone_number, or network is missing
400INVALID_PACKAGEPackage code not found or package is inactive
400NO_PRICEYou haven't set a price for this package yet
400PAYMENT_FAILEDPaystack could not initialize the payment

Get Transaction

GET/api/v1/transactions/:ref

Check 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

ParameterTypeRequiredDescription
:refstringRequiredTransaction reference from POST /purchase (e.g., GD8A3F1B2C)

Request

cURLbash
curl -X GET "https://www.getdatagh.com/api/v1/transactions/GD8A3F1B2C" \
  -H "Authorization: Bearer gdgh_your_api_key_here"

Response

200 OKjson
{
  "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

FieldTypeDescription
transaction_refstringUnique transaction reference
statusstringPayment status (see table below)
data_transfer_statusstringData delivery status (see table below)
package_codestringThe package that was purchased
networkstringMobile network of the recipient
recipient_numberstringPhone number that received the data
amountnumberAmount charged in GHS
created_atstringWhen the transaction was created (ISO 8601)

Payment Status

StatusWhat it means
INITIATEDPayment link created, waiting for customer to pay
PENDINGPayment is being processed
SUCCESSCustomer paid successfully
FAILEDPayment failed or was declined

Data Transfer Status

StatusWhat it means
PENDINGData has not been sent yet
SENTData bundle delivered to recipient
FAILEDData delivery failed — contact support
i
You can only view your own transactions. Looking up another vendor's transaction will return a 404.

Get Balance

GET/api/v1/balance

See how much you've earned. Returns your total sales, commission earned, amount already paid out, and what's still pending.

Request

cURLbash
curl -X GET "https://www.getdatagh.com/api/v1/balance" \
  -H "Authorization: Bearer gdgh_your_api_key_here"

Response

200 OKjson
{
  "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

FieldTypeDescription
total_salesnumberTotal revenue from all successful transactions (GHS)
total_commissionnumberTotal commission earned (GHS)
total_paid_outnumberAmount already paid out to you (GHS)
pending_payoutnumberCommission earned but not yet paid out (GHS)
total_transactionsnumberTotal number of transactions created
successful_transactionsnumberTransactions 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 response structurejson
{
  "error": {
    "message": "A human-readable description of the error",
    "code": "MACHINE_READABLE_CODE"
  }
}

Error Code Reference

HTTP StatusCodeDescriptionWhat to do
401UNAUTHORIZEDMissing or invalid API keyCheck your Authorization header and key format. Make sure you're using the www. URL.
403FORBIDDENVendor account inactiveContact support to reactivate your account
400INVALID_BODYMalformed JSON in request bodyCheck that Content-Type is application/json and body is valid JSON
400MISSING_FIELDSRequired fields not providedInclude package_code, phone_number, and network
400INVALID_PACKAGEPackage code not found or inactiveDouble-check the package_code from GET /packages
400NO_PRICENo price configured for this packageSet a price for this package in your dashboard
400PAYMENT_FAILEDPayment gateway initialization failedTry again. If it keeps happening, contact support.
404NOT_FOUNDTransaction reference not foundCheck the reference and make sure it belongs to your account
429RATE_LIMITEDToo many requestsWait a moment, then try again
500INTERNAL_ERRORServer errorTry again. Contact support if it persists.

Handling Errors in Code

Recommended error handlingjavascript
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

Customer redirect after paymenttext
https://yoursite.com/payment-complete?reference=GD8A3F1B2C
Handle the callback on your serverjavascript
// 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

Don't just trust the redirect. Always call 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.

JS

JavaScript / Node.js

getdatagh.jsjavascript
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);
PY

Python

getdatagh.pypython
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

GetDataGH.phpphp
<?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

All endpoints via cURLbash
# 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.

1

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=MTN
2

Collect customer details

Get the recipient's phone number and network. Optionally collect their email for a payment receipt.

3

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" }
4

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;
5

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=GD8A3F1B2C
6

Verify 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!

The entire purchase and delivery flow is handled by GetDataGH. You just display packages, create the purchase, and redirect the customer. We handle the rest.

Changelog

v1.0

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.com

GetDataGH · API v1 · Last updated April 2026