Look up hashed MSISDN
Resolve a supported Kenyan phone-number hash. Only successful matches are billed.
https://api.dehashit.com/api/v1/Look up hashed MSISDN
/api/v1/msisdn/decrypt/Look up a phone-number hash from an M-Pesa transaction callback. Billable on match only (KES 0.10 per match). Unmatched hashes (404), validation errors (400), rate limits (429), and service outages (503) are free.
Note: The endpoint path keeps the historic /decrypt/ name so existing M-Pesa integrations can adopt it without changes. Submit a supported M-Pesa phone-number hash to retrieve the matching phone number when available.
To safely handle network retries, send an Idempotency-Key header (up to 128 characters). Choose a unique key for each logical lookup, such as your payment ID, and keep that key and hash unchanged for every retry. A successful match is returned again without a second charge; using its key with another hash returns 422 idempotency_key_reused. Failed lookups do not consume the key. Replace the example key payment-order-123 in your integration.
Body parameters
| Name | Type | Required | Description |
|---|---|---|---|
| msisdn_hash | string | required | 64-character hexadecimal hash from the M-Pesa callback. |
Request
curl -X POST https://api.dehashit.com/api/v1/msisdn/decrypt/ \
-H "X-Api-Key: dh_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: payment-order-123" \
-d '{"msisdn_hash": "7132104d6aae9c3fac82095a42c2817952bca48e09d98d5bf4ac08218982fb90"}'import requests
r = requests.post(
"https://api.dehashit.com/api/v1/msisdn/decrypt/",
json={"msisdn_hash": "7132104d6aae9c3fac82095a42c2817952bca48e09d98d5bf4ac08218982fb90"},
headers={
"X-Api-Key": "dh_live_...",
"Idempotency-Key": "payment-order-123",
},
timeout=10,
)
payload = r.json()
if payload["status"]:
print(payload["data"]["msisdn"])
else:
print(r.status_code, payload.get("error_code"))const res = await fetch("https://api.dehashit.com/api/v1/msisdn/decrypt/", {
method: "POST",
headers: {
"X-Api-Key": "dh_live_...",
"Content-Type": "application/json",
"Idempotency-Key": "payment-order-123",
},
body: JSON.stringify({ msisdn_hash: "7132104d6aae9c3fac82095a42c2817952bca48e09d98d5bf4ac08218982fb90" }),
});
const payload = await res.json();
if (payload.status) {
console.log(payload.data.msisdn);
} else {
console.error(res.status, payload.error_code);
}package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]string{
"msisdn_hash": "7132104d6aae9c3fac82095a42c2817952bca48e09d98d5bf4ac08218982fb90",
})
req, _ := http.NewRequest("POST",
"https://api.dehashit.com/api/v1/msisdn/decrypt/", bytes.NewReader(body))
req.Header.Set("X-Api-Key", "dh_live_...")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "payment-order-123")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var out struct {
Status bool `json:"status"`
ErrorCode string `json:"error_code"`
Data struct {
MSISDN string `json:"msisdn"`
Country string `json:"country"`
Carrier string `json:"carrier"`
} `json:"data"`
}
if err := json.NewDecoder(res.Body).Decode(&out); err != nil {
panic(err)
}
if !out.Status {
fmt.Println(res.StatusCode, out.ErrorCode)
return
}
fmt.Println(out.Data.MSISDN, out.Data.Country, out.Data.Carrier)
}Response
{
"status": true,
"status_code": 0,
"message": "Data found",
"data": {
"msisdn": "254712345678",
"country": "Kenya",
"carrier": "Safaricom"
}
}{
"status": false,
"status_code": 404,
"error_code": "not_found",
"message": "No data found.",
"data": {}
}{
"status": false,
"status_code": 402,
"error_code": "insufficient_balance",
"message": "Insufficient balance. Top up your wallet to continue.",
"data": {}
}{
"status": false,
"status_code": 422,
"error_code": "idempotency_key_reused",
"message": "Key was used for a different request.",
"data": {}
}Need a hand with your integration? Contact support.