API reference

Selcom-compatible REST API. All endpoints are POST with JSON bodies.

POST /v1/walletcashin/process

Collect funds from a customer MSISDN (CASHIN).

FieldRequiredDescription
transidYesYour unique transaction id
amountYesAmount in major currency units (e.g. TZS)
msisdnYesCustomer phone number
utilityrefNoYour internal reference (order id, member id)
utilitycodeNoProduct code, e.g. VMCASHIN
vendorNoMerchant vendor id
pinNoVendor PIN if required by integration
countryCodeNoISO country hint: TZ, KE, UG, …
const baseUrl = process.env.LIPACHAP_BASE_URL; // sandbox or live
const path = '/v1/walletcashin/process';
const body = JSON.stringify({
  transid: 'TXN-' + Date.now(),
  utilitycode: 'VMCASHIN',
  utilityref: 'ORDER-123',
  amount: 5000,
  msisdn: '255712345678',
  vendor: 'YOUR_VENDOR',
  pin: '0000',
});

const res = await fetch(baseUrl + path, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: lipachapAuthHeader(apiKey, apiSecret, path, body),
    'X-Request-Id': crypto.randomUUID(),
  },
  body,
});

const data = await res.json();
// { resultcode: '000', result: 'SUCCESS', reference, transid, status, ... }
String path = "/v1/walletcashin/process";
JsonObject payload = new JsonObject();
payload.addProperty("transid", "TXN-" + System.currentTimeMillis());
payload.addProperty("utilitycode", "VMCASHIN");
payload.addProperty("utilityref", "ORDER-123");
payload.addProperty("amount", 5000);
payload.addProperty("msisdn", "255712345678");
payload.addProperty("vendor", "YOUR_VENDOR");
payload.addProperty("pin", "0000");

String body = payload.toString();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", LipachapAuth.authorizationHeader(apiKey, apiSecret, path, body));

ResponseEntity<String> response = restTemplate.exchange(
    baseUrl + path, HttpMethod.POST, new HttpEntity<>(body, headers), String.class);
$path = '/v1/walletcashin/process';
$payload = [
    'transid' => 'TXN-' . time(),
    'utilitycode' => 'VMCASHIN',
    'utilityref' => 'ORDER-123',
    'amount' => 5000,
    'msisdn' => '255712345678',
    'vendor' => 'YOUR_VENDOR',
    'pin' => '0000',
];
$body = json_encode($payload, JSON_UNESCAPED_SLASHES);

$ch = curl_init(getenv('LIPACHAP_BASE_URL') . $path);
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: ' . lipachap_auth_header(getenv('LIPACHAP_API_KEY'), getenv('LIPACHAP_API_SECRET'), $path, $body),
    ],
]);
$response = curl_exec($ch);
import requests

path = "/v1/walletcashin/process"
payload = {
    "transid": f"TXN-{int(time.time())}",
    "utilitycode": "VMCASHIN",
    "utilityref": "ORDER-123",
    "amount": 5000,
    "msisdn": "255712345678",
    "vendor": "YOUR_VENDOR",
    "pin": "0000",
}
body = json.dumps(payload, separators=(",", ":"))

response = requests.post(
    os.environ["LIPACHAP_BASE_URL"] + path,
    data=body,
    headers={
        "Content-Type": "application/json",
        "Authorization": lipachap_auth_header(api_key, api_secret, path, body),
    },
    timeout=30,
)
data = response.json()
path := "/v1/walletcashin/process"
body := `{"transid":"TXN-001","utilitycode":"VMCASHIN","utilityref":"ORDER-123","amount":5000,"msisdn":"255712345678","vendor":"YOUR_VENDOR","pin":"0000"}`

req, _ := http.NewRequest(http.MethodPost, baseURL+path, strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", AuthHeader(apiKey, apiSecret, path, body))

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

POST /v1/gateway/cashin

Disburse funds to an MSISDN (CASHOUT). Include fee fields when your platform pre-calculates charges:

FieldDescription
providerFeeMobile network fee portion
platformFeeLipachap platform fee portion
totalFeeSum of fees
totalChargedAmount debited from sender including fees
const path = '/v1/gateway/cashin';
const body = JSON.stringify({
  transid: 'PAYOUT-' + Date.now(),
  utilityref: 'DISB-456',
  amount: 10000,
  msisdn: '255712345678',
  vendor: 'YOUR_VENDOR',
  pin: '0000',
  providerFee: 0,
  platformFee: 150,
  totalFee: 150,
  totalCharged: 10150,
});

const res = await fetch(baseUrl + path, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: lipachapAuthHeader(apiKey, apiSecret, path, body),
  },
  body,
});
String path = "/v1/gateway/cashin";
JsonObject payload = new JsonObject();
payload.addProperty("transid", "PAYOUT-" + System.currentTimeMillis());
payload.addProperty("utilityref", "DISB-456");
payload.addProperty("amount", 10000);
payload.addProperty("msisdn", "255712345678");
payload.addProperty("vendor", "YOUR_VENDOR");
payload.addProperty("pin", "0000");
payload.addProperty("providerFee", 0);
payload.addProperty("platformFee", 150);
payload.addProperty("totalFee", 150);
payload.addProperty("totalCharged", 10150);

String body = payload.toString();
// POST with Authorization header (same as cash-in)
$path = '/v1/gateway/cashin';
$body = json_encode([
    'transid' => 'PAYOUT-' . time(),
    'utilityref' => 'DISB-456',
    'amount' => 10000,
    'msisdn' => '255712345678',
    'vendor' => 'YOUR_VENDOR',
    'pin' => '0000',
    'providerFee' => 0,
    'platformFee' => 150,
    'totalFee' => 150,
    'totalCharged' => 10150,
], JSON_UNESCAPED_SLASHES);
path = "/v1/gateway/cashin"
body = json.dumps({
    "transid": f"PAYOUT-{int(time.time())}",
    "utilityref": "DISB-456",
    "amount": 10000,
    "msisdn": "255712345678",
    "vendor": "YOUR_VENDOR",
    "pin": "0000",
    "providerFee": 0,
    "platformFee": 150,
    "totalFee": 150,
    "totalCharged": 10150,
}, separators=(",", ":"))
path := "/v1/gateway/cashin"
body := `{"transid":"PAYOUT-001","utilityref":"DISB-456","amount":10000,"msisdn":"255712345678","vendor":"YOUR_VENDOR","pin":"0000","totalCharged":10150}`
req.Header.Set("Authorization", AuthHeader(apiKey, apiSecret, path, body))

POST /v1/checkout/status

Look up a transaction by your transid.

const path = '/v1/checkout/status';
const body = JSON.stringify({ transid: 'TXN-001' });

const res = await fetch(baseUrl + path, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: lipachapAuthHeader(apiKey, apiSecret, path, body),
  },
  body,
});

const txn = await res.json();
// status: PENDING | SUCCESS | FAILED
String path = "/v1/checkout/status";
JsonObject payload = new JsonObject();
payload.addProperty("transid", "TXN-001");
String body = payload.toString();
// POST with signed Authorization header
$path = '/v1/checkout/status';
$body = json_encode(['transid' => 'TXN-001'], JSON_UNESCAPED_SLASHES);
path = "/v1/checkout/status"
body = json.dumps({"transid": "TXN-001"}, separators=(",", ":"))
path := "/v1/checkout/status"
body := `{"transid":"TXN-001"}`

Success response (typical)

{
  "resultcode": "000",
  "result": "SUCCESS",
  "message": "Transaction queued",
  "reference": "LC-ABC123",
  "transid": "TXN-001",
  "providerFee": 0,
  "platformFee": 0,
  "totalFee": 0,
  "totalCharged": 5000,
  "status": "PENDING"
}

resultcode 101 indicates a duplicate transid — treat as idempotent success and use the returned record.

OpenAPI

Download openapi.json