Authentication

All /v1/* payment endpoints require GATEWAY digest auth.

Header format

Authorization: GATEWAY <base64>

Decode the base64 token to apiKey:hexDigest. The digest must match:

hexDigest = sha256(apiSecret + requestPath + rawRequestBody)

Signing rules

Key modes and hosts

HostKey mode
sandbox.api.lipachap.comTEST only
api.lipachap.comLIVE only

Using a TEST key on the live host (or vice versa) returns 401 Unauthorized.

Error responses

{
  "resultcode": "401",
  "resultdesc": "Unauthorized - Invalid digest",
  "status": "FAILED"
}

Implementation samples

const crypto = require('crypto');

function lipachapAuthHeader(apiKey, apiSecret, requestPath, rawBody = '') {
  const digest = crypto
    .createHash('sha256')
    .update(apiSecret + requestPath + rawBody)
    .digest('hex');
  const token = Buffer.from(`${apiKey}:${digest}`).toString('base64');
  return `GATEWAY ${token}`;
}

// Example
const path = '/v1/walletcashin/process';
const body = JSON.stringify({
  transid: 'TXN-001',
  amount: 5000,
  msisdn: '255712345678',
  utilityref: 'ORDER-123',
  utilitycode: 'VMCASHIN',
  vendor: 'YOUR_VENDOR',
  pin: '0000',
});
const authorization = lipachapAuthHeader(process.env.LIPACHAP_API_KEY, process.env.LIPACHAP_API_SECRET, path, body);
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import org.apache.commons.codec.digest.DigestUtils;

public final class LipachapAuth {
  public static String authorizationHeader(String apiKey, String apiSecret, String path, String rawBody) {
    String signed = apiSecret + path + (rawBody == null ? "" : rawBody);
    String digest = DigestUtils.sha256Hex(signed);
    String credentials = apiKey + ":" + digest;
    return "GATEWAY " + Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8));
  }
}

// Usage
String path = "/v1/walletcashin/process";
String body = "{\"transid\":\"TXN-001\",\"amount\":5000,\"msisdn\":\"255712345678\"}";
String auth = LipachapAuth.authorizationHeader(apiKey, apiSecret, path, body);
<?php

function lipachap_auth_header(string $apiKey, string $apiSecret, string $path, string $rawBody = ''): string {
    $digest = hash('sha256', $apiSecret . $path . $rawBody);
    $token = base64_encode($apiKey . ':' . $digest);
    return 'GATEWAY ' . $token;
}

$path = '/v1/walletcashin/process';
$body = json_encode([
    'transid' => 'TXN-001',
    'amount' => 5000,
    'msisdn' => '255712345678',
    'utilityref' => 'ORDER-123',
], JSON_UNESCAPED_SLASHES);

$authorization = lipachap_auth_header(getenv('LIPACHAP_API_KEY'), getenv('LIPACHAP_API_SECRET'), $path, $body);
import base64
import hashlib
import json
import os

def lipachap_auth_header(api_key: str, api_secret: str, path: str, raw_body: str = "") -> str:
    digest = hashlib.sha256((api_secret + path + raw_body).encode("utf-8")).hexdigest()
    token = base64.b64encode(f"{api_key}:{digest}".encode("utf-8")).decode("ascii")
    return f"GATEWAY {token}"

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

authorization = lipachap_auth_header(
    os.environ["LIPACHAP_API_KEY"],
    os.environ["LIPACHAP_API_SECRET"],
    path,
    body,
)
package lipachap

import (
    "crypto/sha256"
    "encoding/base64"
    "encoding/hex"
    "fmt"
)

func AuthHeader(apiKey, apiSecret, path, rawBody string) string {
    sum := sha256.Sum256([]byte(apiSecret + path + rawBody))
    digest := hex.EncodeToString(sum[:])
    token := base64.StdEncoding.EncodeToString([]byte(apiKey + ":" + digest))
    return "GATEWAY " + token
}

// Usage in a handler:
// path := "/v1/walletcashin/process"
// body := `{"transid":"TXN-001","amount":5000,"msisdn":"255712345678"}`
// req.Header.Set("Authorization", AuthHeader(apiKey, apiSecret, path, body))