The eTims (electronic Tax Invoice Management System) API allows you to integrate with the Kenya Revenue Authority (KRA) tax compliance system. Submit sales, manage inventory, generate tax invoices, and maintain full compliance with KRA regulations.
eTims (formerly OSCU - TIMS Online Sales Control Unit) is KRA's electronic tax invoice management system. All VAT-registered businesses in Kenya must use eTims-compliant systems to:
| Scope | Description |
|---|---|
etims:read |
View device info, sales, purchases, stock, items, reports |
etims:write |
Submit sales, purchases, stock movements, manage items |
etims:callback |
Handle KRA callbacks and webhooks |
Retrieve your eTims device configuration and status.
Endpoint: GET /api/etims/device/info
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/device/info \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": {
"tin": "P051234567A",
"bhfid": "00",
"device_serial": "DVC2024001",
"business_name": "My Business Ltd",
"branch_name": "Main Branch",
"status": "active",
"last_sync": "2024-01-20T15:30:00Z",
"initialized": true,
"environment": "production"
}
}
Initialize your device with KRA (first-time setup).
Endpoint: POST /api/etims/device/initialize
Required Scope: etims:write
Request Body:
{
"tin": "P051234567A",
"bhfid": "00",
"device_serial": "DVC2024001",
"environment": "production"
}
Request:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/etims/device/initialize \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"tin": "P051234567A",
"bhfid": "00",
"device_serial": "DVC2024001"
}'
Response:
{
"success": true,
"data": {
"status": "initialized",
"device_id": "DEV-KE-001",
"registration_date": "2024-01-20T16:00:00Z"
},
"message": "Device initialized successfully with KRA"
}
Check connection status with KRA servers.
Endpoint: GET /api/etims/health
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/health \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": {
"status": "healthy",
"kra_server": "reachable",
"last_successful_sync": "2024-01-20T15:30:00Z",
"response_time_ms": 234
}
}
Submit a sale to eTims/KRA.
Endpoint: POST /api/etims/sales/submit
Required Scope: etims:write
Request Body:
{
"receipt_number": "INV-2024-001",
"receipt_date": "2024-01-20",
"customer_pin": "P051234567A",
"customer_name": "John Doe",
"sales_type": "N",
"payment_type": "01",
"items": [
{
"item_seq": 1,
"item_code": "ITEM001",
"item_name": "Product A",
"quantity": 2,
"unit_price": 1000.00,
"discount": 0,
"tax_type": "B",
"tax_rate": 16
},
{
"item_seq": 2,
"item_code": "ITEM002",
"item_name": "Product B",
"quantity": 1,
"unit_price": 500.00,
"discount": 0,
"tax_type": "B",
"tax_rate": 16
}
]
}
Sales Types:
N - Normal saleP - Proforma invoiceT - Training salePayment Types:
01 - Cash02 - Credit03 - Cheque04 - Mobile Money (M-Pesa, etc.)05 - Card06 - OtherTax Types:
A - VAT 0% (Exempt)B - VAT 16% (Standard)C - VAT 8% (Reduced)D - Non-VATRequest:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/etims/sales/submit \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"receipt_number": "INV-2024-001",
"customer_pin": "P051234567A",
"sales_type": "N",
"payment_type": "01",
"items": [
{
"item_seq": 1,
"item_code": "ITEM001",
"quantity": 2,
"unit_price": 1000.00,
"tax_type": "B"
}
]
}'
Response:
{
"success": true,
"data": {
"sale_id": 789,
"receipt_number": "INV-2024-001",
"cu_invoice_number": "CU2024123-001",
"internal_data": "202401200001",
"receipt_signature": "ABCD1234EFGH5678",
"total_amount": 2320.00,
"tax_amount": 320.00,
"status": "submitted",
"submitted_at": "2024-01-20T16:05:00Z",
"qr_code_url": "https://yourtenant.salami.dgl.co.ke/etims/invoice/qr/789"
},
"message": "Sale submitted to eTims successfully"
}
Retrieve details of a submitted sale.
Endpoint: GET /api/etims/sales/{receipt_number}
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/sales/INV-2024-001 \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": {
"id": 789,
"receipt_number": "INV-2024-001",
"cu_invoice_number": "CU2024123-001",
"customer_pin": "P051234567A",
"customer_name": "John Doe",
"total_amount": 2320.00,
"tax_amount": 320.00,
"sales_type": "N",
"payment_type": "01",
"status": "approved",
"items": [...],
"submitted_at": "2024-01-20T16:05:00Z",
"approved_at": "2024-01-20T16:05:15Z"
}
}
Cancel a submitted sale.
Endpoint: POST /api/etims/sales/{receipt_number}/cancel
Required Scope: etims:write
Request Body:
{
"reason": "Customer requested cancellation",
"refund_type": "01"
}
Refund Types:
01 - Cash refund02 - Credit note03 - No refundRequest:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/etims/sales/INV-2024-001/cancel \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"reason": "Customer requested cancellation",
"refund_type": "01"
}'
Response:
{
"success": true,
"data": {
"status": "cancelled",
"cancelled_at": "2024-01-20T16:10:00Z",
"refund_type": "01"
},
"message": "Sale cancelled successfully"
}
Submit a purchase to eTims.
Endpoint: POST /api/etims/purchases/submit
Required Scope: etims:write
Request Body:
{
"invoice_number": "PINV-2024-001",
"invoice_date": "2024-01-20",
"supplier_tin": "P051234567B",
"supplier_name": "Supplier Ltd",
"purchase_type": "N",
"payment_type": "02",
"items": [
{
"item_seq": 1,
"item_code": "ITEM001",
"item_name": "Raw Material A",
"quantity": 10,
"unit_price": 800.00,
"tax_type": "B",
"tax_rate": 16
}
]
}
Purchase Types:
N - Normal purchaseI - Import purchaseRequest:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/etims/purchases/submit \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"invoice_number": "PINV-2024-001",
"supplier_tin": "P051234567B",
"purchase_type": "N",
"payment_type": "02",
"items": [...]
}'
Response:
{
"success": true,
"data": {
"purchase_id": 456,
"invoice_number": "PINV-2024-001",
"total_amount": 9280.00,
"tax_amount": 1280.00,
"status": "submitted",
"submitted_at": "2024-01-20T16:15:00Z"
},
"message": "Purchase submitted successfully"
}
Retrieve details of a purchase.
Endpoint: GET /api/etims/purchases/{invoice_number}
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/purchases/PINV-2024-001 \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": {
"id": 456,
"invoice_number": "PINV-2024-001",
"supplier_tin": "P051234567B",
"supplier_name": "Supplier Ltd",
"total_amount": 9280.00,
"tax_amount": 1280.00,
"purchase_type": "N",
"payment_type": "02",
"status": "approved",
"items": [...],
"submitted_at": "2024-01-20T16:15:00Z"
}
}
Register a new item/product with eTims.
Endpoint: POST /api/etims/items/register
Required Scope: etims:write
Request Body:
{
"item_code": "ITEM001",
"item_name": "Product A",
"item_type": "1",
"origin_country": "KE",
"taxation_type": "B",
"unit_price": 1000.00,
"package_unit": "NT",
"quantity_unit": "U",
"description": "High quality product A"
}
Item Types:
1 - Raw material2 - Finished product3 - ServicePackage Units (Common):
NT - NetGRS - GrossCT - CartonBX - BoxBAG - BagQuantity Units (Common):
U - UnitKG - KilogramM - MeterL - LiterRequest:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/etims/items/register \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"item_code": "ITEM001",
"item_name": "Product A",
"item_type": "2",
"taxation_type": "B",
"unit_price": 1000.00
}'
Response:
{
"success": true,
"data": {
"item_id": 123,
"item_code": "ITEM001",
"status": "registered",
"registered_at": "2024-01-20T16:20:00Z"
},
"message": "Item registered successfully"
}
Retrieve item details.
Endpoint: GET /api/etims/items/{item_code}
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/items/ITEM001 \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": {
"id": 123,
"item_code": "ITEM001",
"item_name": "Product A",
"item_type": "2",
"origin_country": "KE",
"taxation_type": "B",
"unit_price": 1000.00,
"current_stock": 50,
"status": "active",
"created_at": "2024-01-20T16:20:00Z"
}
}
Update item information.
Endpoint: PUT /api/etims/items/{item_code}
Required Scope: etims:write
Request Body:
{
"item_name": "Product A - Updated",
"unit_price": 1200.00,
"description": "Updated description"
}
Request:
curl -X PUT \
https://yourtenant.salami.dgl.co.ke/api/etims/items/ITEM001 \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"unit_price": 1200.00
}'
Response:
{
"success": true,
"data": {
"item_code": "ITEM001",
"status": "updated",
"updated_at": "2024-01-20T16:25:00Z"
},
"message": "Item updated successfully"
}
Record stock movements (additions, reductions, adjustments).
Endpoint: POST /api/etims/stock/movement
Required Scope: etims:write
Request Body:
{
"movement_type": "01",
"movement_date": "2024-01-20",
"reason": "Stock received from supplier",
"items": [
{
"item_code": "ITEM001",
"quantity": 100,
"unit_price": 800.00
}
]
}
Movement Types:
01 - Stock addition (purchase, production)02 - Stock reduction (sale, wastage)03 - Stock adjustment (correction)04 - Stock transfer (between branches)Request:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/etims/stock/movement \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"movement_type": "01",
"reason": "Stock received",
"items": [
{"item_code": "ITEM001", "quantity": 100}
]
}'
Response:
{
"success": true,
"data": {
"movement_id": 234,
"movement_type": "01",
"total_items": 1,
"status": "submitted",
"submitted_at": "2024-01-20T16:30:00Z"
},
"message": "Stock movement recorded successfully"
}
Retrieve current stock levels.
Endpoint: GET /api/etims/stock/current
Required Scope: etims:read
Query Parameters:
item_code (optional) - Filter by specific itemRequest:
curl -X GET \
'https://yourtenant.salami.dgl.co.ke/api/etims/stock/current?item_code=ITEM001' \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": [
{
"item_code": "ITEM001",
"item_name": "Product A",
"quantity": 150,
"unit_price": 1000.00,
"total_value": 150000.00,
"last_movement": "2024-01-20T16:30:00Z"
}
]
}
Code tables contain reference data from KRA (countries, currencies, tax types, etc.).
Retrieve list of country codes.
Endpoint: GET /api/etims/codes/countries
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/codes/countries \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": [
{"code": "KE", "name": "Kenya"},
{"code": "UG", "name": "Uganda"},
{"code": "TZ", "name": "Tanzania"},
{"code": "US", "name": "United States"}
]
}
Retrieve supported currencies.
Endpoint: GET /api/etims/codes/currencies
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/codes/currencies \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": [
{"code": "KES", "name": "Kenyan Shilling", "rate": 1.0},
{"code": "USD", "name": "US Dollar", "rate": 150.5},
{"code": "EUR", "name": "Euro", "rate": 165.2}
]
}
Retrieve payment type codes.
Endpoint: GET /api/etims/codes/payment-types
Required Scope: etims:read
Response:
{
"success": true,
"data": [
{"code": "01", "name": "Cash"},
{"code": "02", "name": "Credit"},
{"code": "04", "name": "Mobile Money"}
]
}
Retrieve tax classification codes.
Endpoint: GET /api/etims/codes/tax-types
Required Scope: etims:read
Response:
{
"success": true,
"data": [
{"code": "A", "name": "VAT 0% (Exempt)", "rate": 0},
{"code": "B", "name": "VAT 16% (Standard)", "rate": 16},
{"code": "C", "name": "VAT 8% (Reduced)", "rate": 8},
{"code": "D", "name": "Non-VAT", "rate": 0}
]
}
Retrieve notices/alerts from KRA.
Endpoint: GET /api/etims/notices
Required Scope: etims:read
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/etims/notices \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": [
{
"notice_id": "NOT-2024-001",
"type": "info",
"title": "System Maintenance",
"message": "eTims will undergo maintenance on 2024-01-25 from 2 AM to 4 AM",
"date": "2024-01-20T10:00:00Z",
"acknowledged": false
}
]
}
Acknowledge receipt of a notice.
Endpoint: POST /api/etims/notices/{notice_id}/acknowledge
Required Scope: etims:write
Request:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/etims/notices/NOT-2024-001/acknowledge \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": {
"notice_id": "NOT-2024-001",
"acknowledged": true,
"acknowledged_at": "2024-01-20T16:40:00Z"
},
"message": "Notice acknowledged"
}
Get sales summary report.
Endpoint: GET /api/etims/reports/sales
Required Scope: etims:read
Query Parameters:
start_date (required) - Start date (YYYY-MM-DD)end_date (required) - End date (YYYY-MM-DD)Request:
curl -X GET \
'https://yourtenant.salami.dgl.co.ke/api/etims/reports/sales?start_date=2024-01-01&end_date=2024-01-20' \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": {
"period": {
"start_date": "2024-01-01",
"end_date": "2024-01-20"
},
"summary": {
"total_sales": 45,
"total_amount": 125000.00,
"total_tax": 17241.38,
"cancelled_sales": 2
},
"by_payment_type": [
{"type": "Cash", "count": 20, "amount": 50000.00},
{"type": "Mobile Money", "count": 25, "amount": 75000.00}
]
}
}
Get purchases summary report.
Endpoint: GET /api/etims/reports/purchases
Required Scope: etims:read
Query Parameters:
start_date (required)end_date (required)Response:
{
"success": true,
"data": {
"summary": {
"total_purchases": 15,
"total_amount": 85000.00,
"total_tax": 11724.14
}
}
}
Get current stock report.
Endpoint: GET /api/etims/reports/stock
Required Scope: etims:read
Response:
{
"success": true,
"data": {
"total_items": 50,
"total_stock_value": 450000.00,
"low_stock_items": 5,
"out_of_stock_items": 2
}
}
<?php
$apiToken = 'your_api_token_here';
$baseUrl = 'https://yourtenant.salami.dgl.co.ke/api';
$data = [
'receipt_number' => 'INV-2024-001',
'customer_pin' => 'P051234567A',
'customer_name' => 'John Doe',
'sales_type' => 'N',
'payment_type' => '01',
'items' => [
[
'item_seq' => 1,
'item_code' => 'ITEM001',
'item_name' => 'Product A',
'quantity' => 2,
'unit_price' => 1000.00,
'tax_type' => 'B',
'tax_rate' => 16
]
]
];
$ch = curl_init("$baseUrl/etims/sales/submit");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiToken,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if ($result['success']) {
echo "Sale submitted!\n";
echo "CU Invoice: " . $result['data']['cu_invoice_number'] . "\n";
echo "Total: KES " . $result['data']['total_amount'] . "\n";
} else {
echo "Error: " . $result['message'] . "\n";
}
const apiToken = 'your_api_token_here';
const baseUrl = 'https://yourtenant.salami.dgl.co.ke/api';
const itemData = {
item_code: 'ITEM001',
item_name: 'Product A',
item_type: '2',
taxation_type: 'B',
unit_price: 1000.00,
package_unit: 'NT',
quantity_unit: 'U'
};
fetch(`${baseUrl}/etims/items/register`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(itemData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Item registered:', data.data.item_code);
} else {
console.error('Error:', data.message);
}
});
import requests
from datetime import datetime, timedelta
api_token = 'your_api_token_here'
base_url = 'https://yourtenant.salami.dgl.co.ke/api'
# Get last 30 days of sales
end_date = datetime.now()
start_date = end_date - timedelta(days=30)
params = {
'start_date': start_date.strftime('%Y-%m-%d'),
'end_date': end_date.strftime('%Y-%m-%d')
}
headers = {
'Authorization': f'Bearer {api_token}'
}
response = requests.get(
f'{base_url}/etims/reports/sales',
headers=headers,
params=params
)
result = response.json()
if result['success']:
summary = result['data']['summary']
print(f"Total Sales: {summary['total_sales']}")
print(f"Total Amount: KES {summary['total_amount']}")
print(f"Total Tax: KES {summary['total_tax']}")
else:
print(f"Error: {result['message']}")
Timing
Data Validation
Error Handling
Registration
Updates
Accuracy
Compliance
Data Security
Compliance
Testing
| Error Code | Message | Solution |
|---|---|---|
DEVICE_NOT_INITIALIZED |
Device not registered with KRA | Initialize device first |
INVALID_PIN |
Invalid customer/supplier PIN | Verify PIN format |
ITEM_NOT_FOUND |
Item not registered | Register item first |
DUPLICATE_INVOICE |
Invoice number already used | Use unique invoice numbers |
INVALID_TAX_TYPE |
Invalid tax classification | Check tax type codes |
CONNECTION_FAILED |
Cannot reach KRA server | Check network, retry later |
VALIDATION_FAILED |
Data validation error | Review and fix field values |
Back to: Payments API Reference | SMS API Reference