Salami Gateway

API Documentation
Back to Dashboard

eTims API Reference

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.

Table of Contents

  1. Overview
  2. Device & Configuration
  3. Sales Operations
  4. Purchase Operations
  5. Item Management
  6. Stock Operations
  7. Code Tables
  8. Notices from KRA
  9. Reports
  10. Code Examples
  11. Best Practices

Overview

What is eTims/OSCU?

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:

Required Scopes

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

Important Notes

Device & Configuration

Get Device Info

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 Device

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

Health Check

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

Sales Operations

Submit Sale

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:

Payment Types:

Tax Types:

Request:

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

Get Sale

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 Sale

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:

Request:

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

Purchase Operations

Submit Purchase

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:

Request:

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

Get Purchase

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

Item Management

Register Item

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:

Package Units (Common):

Quantity Units (Common):

Request:

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

Get Item

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

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

Stock Operations

Submit Stock Movement

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:

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

Get Current Stock

Retrieve current stock levels.

Endpoint: GET /api/etims/stock/current

Required Scope: etims:read

Query Parameters:

Request:

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

Code tables contain reference data from KRA (countries, currencies, tax types, etc.).

Get Countries

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

Get Currencies

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}
  ]
}

Get Payment Types

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

Get Tax Types

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}
  ]
}

Notices from KRA

Get Notices

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 Notice

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

Reports

Sales Report

Get sales summary report.

Endpoint: GET /api/etims/reports/sales

Required Scope: etims:read

Query Parameters:

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}
    ]
  }
}

Purchases Report

Get purchases summary report.

Endpoint: GET /api/etims/reports/purchases

Required Scope: etims:read

Query Parameters:

Response:

{
  "success": true,
  "data": {
    "summary": {
      "total_purchases": 15,
      "total_amount": 85000.00,
      "total_tax": 11724.14
    }
  }
}

Stock Report

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

Code Examples

PHP Example: Submit Sale

<?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";
}

JavaScript Example: Register Item

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);
  }
});

Python Example: Get Sales Report

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']}")

Best Practices

Sales Submission

  1. Timing

    • Submit sales to KRA within 24 hours
    • Batch submissions during off-peak hours
    • Don't submit future-dated sales
  2. Data Validation

    • Verify customer PIN format (P051234567A)
    • Ensure all items are pre-registered
    • Validate tax calculations
    • Check total amounts before submission
  3. Error Handling

    • Retry failed submissions
    • Log all submission attempts
    • Keep offline backup of invoices
    • Handle network timeouts gracefully

Item Management

  1. Registration

    • Register all items before first use
    • Use consistent naming conventions
    • Assign proper tax classifications
    • Keep item codes unique and meaningful
  2. Updates

    • Update prices regularly
    • Sync item changes with KRA
    • Maintain item master data
    • Track discontinued items

Stock Management

  1. Accuracy

    • Conduct regular stock counts
    • Record all movements promptly
    • Reconcile physical vs system stock
    • Document adjustments
  2. Compliance

    • Submit stock movements within 24 hours
    • Maintain proper documentation
    • Keep audit trail of all changes

Security & Compliance

  1. Data Security

    • Protect KRA credentials
    • Use HTTPS only
    • Implement access controls
    • Regular security audits
  2. Compliance

    • Follow KRA guidelines
    • Keep records for 5+ years
    • Respond to KRA notices promptly
    • Stay updated on regulation changes
  3. Testing

    • Test in sandbox environment first
    • Validate all integrations
    • Test error scenarios
    • Conduct regular audits

Common Errors

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

KRA Support

Need Help?


Back to: Payments API Reference | SMS API Reference


Need help? Contact us at support@dgl.co.ke
© 2026 Deadan Group Limited. All rights reserved.
⚡ API Explorer
LIVE
// Response will appear here...