Batch decode
Upload a CSV of phone-number hashes and download results for every row.
https://api.dehashit.com/api/v1/Batch decode
/api/v1/batch/Decode up to 5,000 phone-number hashes in one CSV upload. New uploads are processed during the request; completed jobs have data.job.status set to done. Each matched row costs KES 0.10; unmatched, invalid, and insufficient-balance rows are free. Duplicate matching rows are each billed separately.
Send X-Batch-Key to make retries safe. Keep it unchanged when retrying the same upload; a completed job is returned without processing or billing again. Reusing the key with different bytes returns 422 idempotency_key_reused; use a new key for a new file. While the same upload is processing, retries return 409 idempotency_key_in_progress.
CSV and headers
| Field | Requirement |
|---|---|
| Body | Raw UTF-8 CSV, up to 2 MiB and 5,000 data rows. Do not send multipart form data. |
| msisdn_hash | Required column containing a 64-character hexadecimal phone-number hash per row. |
| Content-Type | text/csv |
| X-Api-Key | Your API key. All batch job and results operations require authentication. |
| X-Batch-Key | Optional retry key, up to 128 characters. Recommended for every upload. |
| X-Batch-Filename | Optional filename for job metadata; stored up to 256 characters. |
Save this example as hashes.csv, or start from the CSV template.
hashes.csv
msisdn_hash
7132104d6aae9c3fac82095a42c2817952bca48e09d98d5bf4ac08218982fb90Request
curl -X POST https://api.dehashit.com/api/v1/batch/ \
-H "X-Api-Key: dh_live_..." -H "Content-Type: text/csv" \
-H "X-Batch-Key: campaign-2026-10-01" \
--data-binary @hashes.csvimport requests
with open("hashes.csv", "rb") as f:
r = requests.post(
"https://api.dehashit.com/api/v1/batch/",
data=f,
headers={
"X-Api-Key": "dh_live_...",
"Content-Type": "text/csv",
"X-Batch-Key": "campaign-2026-10-01",
},
timeout=30,
)
job = r.json()["data"]["job"] # {"status": "done", "matched_count": ...}import { readFileSync } from "node:fs";
const res = await fetch("https://api.dehashit.com/api/v1/batch/", {
method: "POST",
headers: {
"X-Api-Key": "dh_live_...",
"Content-Type": "text/csv",
"X-Batch-Key": "campaign-2026-10-01",
},
body: readFileSync("hashes.csv"),
});
const { data } = await res.json(); // data.job: { status, row_count, ... }package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
csv, err := os.ReadFile("hashes.csv")
if err != nil {
panic(err)
}
req, _ := http.NewRequest("POST",
"https://api.dehashit.com/api/v1/batch/", bytes.NewReader(csv))
req.Header.Set("X-Api-Key", "dh_live_...")
req.Header.Set("Content-Type", "text/csv")
req.Header.Set("X-Batch-Key", "campaign-2026-10-01")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
fmt.Println(res.Status)
}Response
{
"status": true,
"status_code": 0,
"message": "Batch ready.",
"data": {
"job": {
"id": 7,
"status": "done",
"row_count": 1,
"completed_rows": 1,
"matched_count": 1,
"unmatched_count": 0,
"invalid_count": 0,
"charged_cents": 10,
"filename": "",
"error": "",
"created_at": "2026-10-17T09:00:00",
"finished_at": "2026-10-17T09:00:01"
}
}
}msisdn_hash,msisdn,status,detail
7132104d6aae9c3fac82095a42c2817952bca48e09d98d5bf4ac08218982fb90,254712345678,match,SafaricomDownload results
Use the returned data.job.id to read the job or download its CSV. Results expire after 24 hours; save them promptly. API-key jobs are accessible only with the creating key within its organization. Browser-created jobs are scoped to the creating user and organization, across that user’s login sessions, and are separate from API-key jobs. Rotating a key does not grant the new key access to the old key’s jobs. Requests outside these scopes or for expired results return 404. Results that are not ready return 409.
| Method and path | Returns |
|---|---|
GET /api/v1/batch/ | The latest 50 jobs for the calling key or browser actor and organization, as an array in data. |
GET /api/v1/batch/{job_id}/ | A single job in data.job. |
GET /api/v1/batch/{job_id}/results/ | A CSV file, rather than a JSON envelope. |
Download a finished job
# Replace 7 with data.job.id from your upload response.
curl "https://api.dehashit.com/api/v1/batch/7/results/" \
-H "X-Api-Key: dh_live_..." \
--output batch-7-results.csvCheck each row’s status: match, no_match, invalid, or insufficient_balance. A finished job can include unpaid rows. After topping up, upload only those rows with a new batch key to avoid charging previously matched rows again.
Need a hand with your integration? Contact support.