Transaction Inquiry
Query the status and details of your transactions.
Overview​
The Transaction Inquiry API allows you to check the current status and retrieve details of any transaction using various identifiers.
Endpoint​
GET /payment-service/transaction/{transaction_id}
Authentication​
Requires Bearer token authentication:
Authorization: Bearer YOUR_API_TOKEN
Query Methods​
By Transaction ID​
GET /payment-service/transaction/TXN_123456789
By Reference Number​
GET /payment-service/transaction?reference=GCA_REF_987654321
By External ID​
GET /payment-service/transaction?external_id=YOUR_REF_123
Response Example​
Successful Transaction​
{
"status": "success",
"transaction": {
"id": "TXN_123456789",
"reference": "GCA_REF_987654321",
"external_id": "YOUR_REF_123",
"type": "collection",
"amount": "1000",
"currency": "TZS",
"phone_number": "+255683542710",
"network": "airtel_money",
"status": "SUCCESS",
"created_at": "2024-03-15T10:25:00Z",
"completed_at": "2024-03-15T10:30:00Z",
"merchant_id": "MERCHANT_123",
"fees": {
"merchant_fee": "25.00",
"customer_fee": "0.00",
"total_fee": "25.00"
},
"settlement": {
"net_amount": "975.00",
"settled_at": "2024-03-15T18:00:00Z",
"settlement_batch": "BATCH_20240315"
}
}
}
Failed Transaction​
{
"status": "success",
"transaction": {
"id": "TXN_987654321",
"reference": "GCA_REF_123456789",
"external_id": "FAILED_REF_456",
"type": "disbursement",
"amount": "1000",
"currency": "TZS",
"phone_number": "+255683542710",
"network": "airtel_money",
"status": "FAILED",
"failure_reason": "RECIPIENT_NOT_FOUND",
"created_at": "2024-03-15T11:00:00Z",
"failed_at": "2024-03-15T11:02:00Z",
"merchant_id": "MERCHANT_123"
}
}
Transaction Not Found​
{
"status": "error",
"message": "Transaction not found",
"error_code": "TRANSACTION_NOT_FOUND"
}
Implementation Examples​
JavaScript/Node.js​
const axios = require('axios');
async function getTransactionStatus(transactionId) {
try {
const response = await axios.get(
`https://gcapay.site/api/v1/payment-service/transaction/${transactionId}`,
{
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN'
}
}
);
return response.data.transaction;
} catch (error) {
if (error.response?.status === 404) {
console.log('Transaction not found');
return null;
}
throw error;
}
}
async function getTransactionByReference(reference) {
try {
const response = await axios.get(
'https://gcapay.site/api/v1/payment-service/transaction',
{
params: { reference },
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN'
}
}
);
return response.data.transaction;
} catch (error) {
console.error('Query failed:', error.response?.data);
throw error;
}
}
// Usage examples
async function examples() {
// Get by transaction ID
const txn1 = await getTransactionStatus('TXN_123456789');
console.log('Transaction status:', txn1?.status);
// Get by reference
const txn2 = await getTransactionByReference('GCA_REF_987654321');
console.log('Transaction amount:', txn2?.amount);
}
Python​
import requests
class GCAPayClient:
def __init__(self, api_token):
self.api_token = api_token
self.base_url = "https://gcapay.site/api/v1"
self.headers = {
"Authorization": f"Bearer {api_token}"
}
def get_transaction(self, transaction_id):
"""Get transaction by ID"""
url = f"{self.base_url}/payment-service/transaction/{transaction_id}"
response = requests.get(url, headers=self.headers)
if response.status_code == 404:
return None
response.raise_for_status()
return response.json()['transaction']
def get_transaction_by_reference(self, reference):
"""Get transaction by reference number"""
url = f"{self.base_url}/payment-service/transaction"
params = {"reference": reference}
response = requests.get(url, params=params, headers=self.headers)
if response.status_code == 404:
return None
response.raise_for_status()
return response.json()['transaction']
def get_transaction_by_external_id(self, external_id):
"""Get transaction by your external ID"""
url = f"{self.base_url}/payment-service/transaction"
params = {"external_id": external_id}
response = requests.get(url, params=params, headers=self.headers)
if response.status_code == 404:
return None
response.raise_for_status()
return response.json()['transaction']
# Usage
client = GCAPayClient("YOUR_API_TOKEN")
# Get by transaction ID
transaction = client.get_transaction("TXN_123456789")
if transaction:
print(f"Status: {transaction['status']}")
print(f"Amount: {transaction['amount']} {transaction['currency']}")
# Get by reference
transaction = client.get_transaction_by_reference("GCA_REF_987654321")
if transaction:
print(f"Transaction found: {transaction['id']}")
PHP​
<?php
class GCAPayClient {
private $apiToken;
private $baseUrl = 'https://gcapay.site/api/v1';
public function __construct($apiToken) {
$this->apiToken = $apiToken;
}
private function makeRequest($url, $params = []) {
$headers = [
'Authorization: Bearer ' . $this->apiToken,
'Content-Type: application/json'
];
if (!empty($params)) {
$url .= '?' . http_build_query($params);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 404) {
return null;
}
if ($httpCode !== 200) {
throw new Exception("API request failed with status $httpCode: $response");
}
$data = json_decode($response, true);
return $data['transaction'] ?? null;
}
public function getTransaction($transactionId) {
$url = $this->baseUrl . '/payment-service/transaction/' . $transactionId;
return $this->makeRequest($url);
}
public function getTransactionByReference($reference) {
$url = $this->baseUrl . '/payment-service/transaction';
return $this->makeRequest($url, ['reference' => $reference]);
}
public function getTransactionByExternalId($externalId) {
$url = $this->baseUrl . '/payment-service/transaction';
return $this->makeRequest($url, ['external_id' => $externalId]);
}
}
// Usage
try {
$client = new GCAPayClient('YOUR_API_TOKEN');
// Get by transaction ID
$transaction = $client->getTransaction('TXN_123456789');
if ($transaction) {
echo "Status: " . $transaction['status'] . "\n";
echo "Amount: " . $transaction['amount'] . " " . $transaction['currency'] . "\n";
} else {
echo "Transaction not found\n";
}
// Get by reference
$transaction = $client->getTransactionByReference('GCA_REF_987654321');
if ($transaction) {
echo "Transaction ID: " . $transaction['id'] . "\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>
Transaction Statuses​
Collection Statuses​
Status | Description | Final |
---|---|---|
PENDING | Customer prompted to pay | No |
SUCCESS | Payment completed | Yes |
FAILED | Payment failed/rejected | Yes |
TIMEOUT | Payment request expired | Yes |
Disbursement Statuses​
Status | Description | Final |
---|---|---|
PROCESSING | Being processed | No |
SUCCESS | Money sent successfully | Yes |
FAILED | Disbursement failed | Yes |
INSUFFICIENT_FUNDS | Not enough balance | Yes |
Polling Best Practices​
When polling for transaction status:
Exponential Backoff​
async function waitForTransactionCompletion(transactionId, maxWaitTime = 300000) {
const startTime = Date.now();
let delay = 1000; // Start with 1 second
while (Date.now() - startTime < maxWaitTime) {
const transaction = await getTransactionStatus(transactionId);
if (!transaction) {
throw new Error('Transaction not found');
}
// Check if transaction is in final state
const finalStatuses = ['SUCCESS', 'FAILED', 'TIMEOUT', 'INSUFFICIENT_FUNDS'];
if (finalStatuses.includes(transaction.status)) {
return transaction;
}
// Wait before next poll
await new Promise(resolve => setTimeout(resolve, delay));
// Increase delay for next iteration (exponential backoff)
delay = Math.min(delay * 1.5, 30000); // Max 30 seconds
}
throw new Error('Transaction polling timeout');
}
// Usage
try {
const finalTransaction = await waitForTransactionCompletion('TXN_123456789');
console.log('Final status:', finalTransaction.status);
} catch (error) {
console.error('Polling failed:', error.message);
}
Rate Limiting​
- Maximum: 60 requests per minute per merchant
- Recommended: 1 request every 10 seconds for active polling
- Burst: Short bursts of 10 requests allowed
Transaction History​
Get multiple transactions with pagination:
GET /payment-service/transactions?page=1&limit=50&status=SUCCESS&from=2024-03-01&to=2024-03-31
Query Parameters​
Parameter | Type | Description |
---|---|---|
page | integer | Page number (default: 1) |
limit | integer | Items per page (max: 100) |
status | string | Filter by status |
type | string | Filter by type (collection/disbursement) |
from | date | Start date (YYYY-MM-DD) |
to | date | End date (YYYY-MM-DD) |
Response Example​
{
"status": "success",
"transactions": [...],
"pagination": {
"current_page": 1,
"total_pages": 5,
"total_count": 248,
"per_page": 50
}
}
Error Handling​
Common error responses:
{
"status": "error",
"message": "Transaction not found",
"error_code": "TRANSACTION_NOT_FOUND"
}
{
"status": "error",
"message": "Invalid transaction ID format",
"error_code": "INVALID_TRANSACTION_ID"
}
{
"status": "error",
"message": "Rate limit exceeded",
"error_code": "RATE_LIMIT_EXCEEDED",
"retry_after": 60
}
Use Cases​
Order Status Updates​
async function updateOrderStatus(orderId, transactionId) {
const transaction = await getTransactionStatus(transactionId);
if (transaction) {
switch (transaction.status) {
case 'SUCCESS':
await updateOrder(orderId, { status: 'paid', paid_at: transaction.completed_at });
break;
case 'FAILED':
await updateOrder(orderId, { status: 'payment_failed', failure_reason: transaction.failure_reason });
break;
case 'PENDING':
await updateOrder(orderId, { status: 'awaiting_payment' });
break;
}
}
}
Reconciliation​
async function reconcileTransactions(date) {
const transactions = await getTransactionHistory({
from: date,
to: date,
limit: 100
});
for (const transaction of transactions) {
await reconcileTransaction(transaction);
}
}
Next Steps​
- Collections API → - Accept customer payments
- Disbursements API → - Send money to recipients
- Webhooks → - Handle real-time status updates