Skip to Content
C-Tax v1.0 is now available
API ReferenceTransactions API

Transactions API

Manage and monitor all transaction types across your account. The Transactions API provides a unified view of sales, purchases, and stock movements.

Overview

Transactions represent business operations that need to be reported to KRA. Each transaction goes through a lifecycle from creation to completion or failure.

Transaction Types

TypeDescription
salesSales to customers
purchasePurchases from suppliers
stockStock movements and adjustments
importImported items

Transaction Statuses

StatusDescription
pendingCreated, awaiting processing
processingBeing sent to KRA
successSuccessfully processed
failedProcessing failed

List Transactions

Get all transactions with optional filtering.

GET/api/v1/transactions

List Transactions

Retrieve all transactions with optional filters by type, status, branch, and date range.

Authentication
Parameters
type
string · query

Filter by type: sales, purchase, stock

status
string · query

Filter by status: pending, processing, success, failed

branch_id
string · query

Filter by branch ID

from_date
string · query

Start date (YYYY-MM-DD)

to_date
string · query

End date (YYYY-MM-DD)

per_page
number · query

Results per page (max 100, default 50)

page
number · query

Page number (default 1)

Response

Status: 200 OK

{ "data": [ { "transaction_id": "9d3f4b1a-7c8e-4d2f-b5a6-1e3c9f8d2b4a", "type": "sales", "status": "success", "branch_id": "00", "invoice_no": "INV-2025-001", "receipt_no": "20250115-00-00001", "synced_to_kra": true, "can_retry": false, "created_at": "2025-01-15T14:30:00Z", "processed_at": "2025-01-15T14:30:05Z" }, { "transaction_id": "8c2e3a0f-6b7d-4c1e-a4b5-0d2c8e7f1a3b", "type": "purchase", "status": "failed", "branch_id": "00", "invoice_no": "PO-2025-001", "receipt_no": null, "synced_to_kra": false, "can_retry": true, "created_at": "2025-01-15T14:25:00Z", "processed_at": "2025-01-15T14:25:10Z" } ], "meta": { "current_page": 1, "per_page": 50, "total": 156, "total_pages": 4 } }

Get Transaction Details

Retrieve complete details of a specific transaction.

GET/api/v1/transactions/{id}

Get Transaction Details

Retrieve complete details of a specific transaction including request and response data.

Authentication
Parameters
id*
string · path

Transaction UUID

Response

Status: 200 OK

{ "status": "success", "data": { "transaction_id": "9d3f4b1a-7c8e-4d2f-b5a6-1e3c9f8d2b4a", "type": "sales", "status": "success", "branch_id": "00", "invoice_no": "INV-2025-001", "receipt_no": "20250115-00-00001", "request_data": { "branch_id": "00", "invoice_no": "INV-2025-001", "sale_date": "20250115", "sale_time": "143000", "payment_type": "CASH", "customer_name": "John Doe", "customer_tin": "", "items": [ { "item_code": "ITEM001", "item_name": "Product A", "quantity": 2, "unit_price": 1000, "supply_amount": 2000, "tax_type": "A", "tax_rate": 16, "tax_amount": 320, "total_amount": 2320 } ] }, "response_data": { "receipt_no": "20250115-00-00001", "receipt_date": "2025-01-15", "qr_code": "data:image/png;base64,..." }, "synced_to_kra": true, "can_retry": false, "created_at": "2025-01-15T14:30:00Z", "processed_at": "2025-01-15T14:30:05Z" } }

Status: 404 Not Found

{ "status": "error", "message": "Transaction not found" }

Retry Failed Transaction

Retry a transaction that previously failed.

POST/api/v1/transactions/{id}/retry

Retry Failed Transaction

Retry a transaction that previously failed. Only transactions with can_retry=true can be retried.

Authentication
Parameters
id*
string · path

Transaction UUID

Request BodyJSON

Response

Status: 200 OK (Retry successful)

{ "status": "success", "message": "Transaction processed successfully with KRA", "data": { "transaction_id": "8c2e3a0f-6b7d-4c1e-a4b5-0d2c8e7f1a3b", "status": "success", "synced_to_kra": true, "receipt_no": "20250115-00-00002" }, "meta": { "timestamp": "2025-01-15T15:00:00Z" } }

Status: 422 Unprocessable Entity (Cannot retry)

{ "status": "error", "message": "Transaction cannot be retried", "reason": "Maximum retry attempts reached" }

Status: 422 Unprocessable Entity (Retry failed)

{ "status": "error", "message": "Transaction could not be processed. Please try again.", "data": { "transaction_id": "8c2e3a0f-6b7d-4c1e-a4b5-0d2c8e7f1a3b", "synced_to_kra": false, "can_retry": true }, "meta": { "timestamp": "2025-01-15T15:00:00Z" } }

Retry Conditions

A transaction can only be retried if:

  • Status is failed
  • Retry count is less than 3
  • Transaction is not already being processed

Transaction Statistics

Get aggregated statistics for transactions.

GET/api/v1/transactions/stats

Transaction Statistics

Get aggregated statistics for transactions including counts by status and type.

Authentication
Parameters
from_date
string · query

Start date (YYYY-MM-DD), default: 30 days ago

to_date
string · query

End date (YYYY-MM-DD), default: today

Response

Status: 200 OK

{ "status": "success", "data": { "total": 256, "by_status": { "success": 240, "failed": 10, "pending": 4, "processing": 2 }, "by_type": { "sales": 180, "purchase": 56, "stock": 20 }, "success_rate": 93.75 }, "period": { "from": "2024-12-16", "to": "2025-01-15" } }

Async Processing

For high-volume scenarios, transactions can be processed asynchronously:

Create Async Transaction

POST /api/v1/sales?async=true

Returns immediately with transaction ID:

{ "status": "processing", "message": "Transaction is being processed", "data": { "transaction_id": "9d3f4b1a-7c8e-4d2f-b5a6-1e3c9f8d2b4a", "invoice_no": "INV-2025-001", "status": "pending" }, "meta": { "timestamp": "2025-01-15T14:30:00Z", "request_id": "req_abc123", "check_status_url": "/api/v1/transactions/9d3f4b1a-7c8e-4d2f-b5a6-1e3c9f8d2b4a" } }

Check Status

Poll the transaction endpoint or use webhooks for real-time updates:

// Polling approach async function waitForTransaction(transactionId) { while (true) { const response = await axios.get(`/api/v1/transactions/${transactionId}`, { headers: { Authorization: `Bearer ${apiKey}` } }); const { status } = response.data.data; if (status === 'success' || status === 'failed') { return response.data.data; } // Wait 2 seconds before next check await new Promise(resolve => setTimeout(resolve, 2000)); } }

Webhook Notification

Configure webhooks to receive instant notifications:

{ "event": "transaction.completed", "timestamp": "2025-01-15T14:30:05Z", "data": { "transaction_id": "9d3f4b1a-7c8e-4d2f-b5a6-1e3c9f8d2b4a", "type": "sales", "status": "success", "invoice_no": "INV-2025-001", "receipt_no": "20250115-00-00001" } }

Transaction Lifecycle

Created (pending) Processing ├── Success ──────► Complete └── Failed ├── Can Retry ──► Processing (retry) └── Max Retries Reached ──► Permanently Failed

Status Transitions

FromToTrigger
pendingprocessingQueue processes transaction
processingsuccessKRA accepts transaction
processingfailedKRA rejects or error occurs
failedprocessingManual or automatic retry

Code Examples

JavaScript

const axios = require('axios'); const apiKey = process.env.CTAX_API_KEY; const baseURL = 'https://c-tax.1809ltd.co.ke/api/v1'; // List transactions const response = await axios.get(`${baseURL}/transactions`, { params: { type: 'sales', status: 'success', from_date: '2025-01-01', to_date: '2025-01-31', per_page: 50 }, headers: { Authorization: `Bearer ${apiKey}` } }); const transactions = response.data.data; // Get statistics const stats = await axios.get(`${baseURL}/transactions/stats`, { headers: { Authorization: `Bearer ${apiKey}` } }); console.log(`Success rate: ${stats.data.data.success_rate}%`); console.log(`Total transactions: ${stats.data.data.total}`);

PHP

use GuzzleHttp\Client; $client = new Client([ 'base_uri' => 'https://c-tax.1809ltd.co.ke/api/v1/', 'headers' => [ 'Authorization' => 'Bearer ' . env('CTAX_API_KEY'), 'Content-Type' => 'application/json', ], ]); // List transactions $response = $client->get('transactions', [ 'query' => [ 'type' => 'sales', 'status' => 'success', 'from_date' => '2025-01-01', 'to_date' => '2025-01-31', ], ]); $transactions = json_decode($response->getBody(), true)['data']; // Get statistics $statsResponse = $client->get('transactions/stats', [ 'query' => [ 'from_date' => '2025-01-01', 'to_date' => '2025-01-31', ], ]); $stats = json_decode($statsResponse->getBody(), true)['data']; echo "Success rate: {$stats['success_rate']}%\n";

Python

import requests import os api_key = os.environ['CTAX_API_KEY'] base_url = 'https://c-tax.1809ltd.co.ke/api/v1' headers = {'Authorization': f'Bearer {api_key}'} # List transactions response = requests.get( f'{base_url}/transactions', params={ 'type': 'sales', 'status': 'success', 'from_date': '2025-01-01', 'to_date': '2025-01-31' }, headers=headers ) transactions = response.json()['data'] # Get statistics stats = requests.get(f'{base_url}/transactions/stats', headers=headers) print(f"Success rate: {stats.json()['data']['success_rate']}%")

Error Handling

Common Errors

500 Internal Server Error

{ "status": "error", "message": "Failed to retrieve transactions" }

404 Not Found

{ "status": "error", "message": "Transaction not found" }

Handling Failed Transactions

  1. Check transaction details to understand the failure
  2. Verify the request data is correct
  3. Check VSCU device connectivity
  4. Retry if can_retry is true
  5. Contact support if issue persists

Best Practices

  1. Use Async for Bulk - Use async processing for high-volume transactions
  2. Implement Webhooks - Use webhooks instead of polling for status updates
  3. Monitor Success Rate - Track statistics and investigate drops in success rate
  4. Handle Retries - Implement retry logic for failed transactions
  5. Store Transaction IDs - Keep transaction IDs for reference and debugging
  6. Use Idempotency - Use unique invoice numbers to prevent duplicates

Last updated on