Bulk Lookup
Validate and enrich up to 1,000 phone numbers in one API call. Receive a full per-number HLR payload plus summary statistics ideal for list hygiene, campaign prep, and fraud screening.
Up to 1,000 Numbers
Submit large contact lists in a single request instead of hammering the single-lookup endpoint.
Pre-flight Validation
Invalid entries are reported per index without blocking valid numbers in the same batch.
Summary Analytics
Aggregate counts for reachable, ported, by networkType, and total cost in one response.
Per-row Billing
Only successful HLR rows incur cost. Validation-only failures are free and listed in errors.
Authentication
Authorization: Basic <token>. Auth guide →1,000
per request
256 KB
JSON payload size
10/s
bulk requests per API key
60s
client recommendation
Bulk processing notes
- Maximum 1,000 numbers per request — split larger lists client-side
- Duplicate MSISDNs in the same batch are processed once when possible
- Ensure credits cover the full batch before submitting large jobs
- Prefer bulk over looping
POST /v1/lookupto avoid rate limits
Endpoint
POST https://api.sendexa.co/v1/lookup/bulkContent-Type: application/jsonAuthorization: Basic YOUR_DASHBOARD_TOKEN
Request Body
{"numbers": [{ "msisdn": "0244123456", "countryCode": "GH", "reference": "lead-1" },{ "msisdn": "0209876543", "countryCode": "GH", "reference": "lead-2" },{ "msisdn": "+233555539152", "reference": "lead-3" }],"defaultCountryCode": "GH"}
| Field | Type | Required | Description |
|---|---|---|---|
| numbers | array | required | List of numbers to look up (1–1000). Each item requires msisdn. |
| numbers[].msisdn | string | required | Phone number in local or international format. |
| numbers[].countryCode | string | optional | Per-number ISO alpha-2 override (falls back to defaultCountryCode). |
| numbers[].reference | string | optional | Your row ID echoed on the matching result (max 64 chars). |
| defaultCountryCode | string | optional | Default ISO country when an entry omits countryCode. |
| campaignName | string | optional | Optional label for dashboards and reconciliation. |
Processing Pipeline
Accept & auth
Validate token and request schema
Normalize
Parse msisdn list, apply default countryCode
HLR fan-out
Query networks for each valid number in parallel batches
Aggregate
Build results[], summary, and total cost
Response
{"success": true,"code": "BULK_LOOKUP_OK","message": "Bulk number lookup completed.","requestId": "REQ-1782003000111","timestamp": "2026-07-12T11:02:18.440Z","data": {"bulkId": "BLK-4c8e1a20-9d3f-4b11-a6e2-88f0c1d2e3f4","campaignName": null,"total": 3,"succeeded": 3,"failed": 0,"summary": {"reachable": 2,"unreachable": 1,"ported": 1,"roaming": 0,"byNetworkType": {"mobile": 2,"fixed": 0,"voip": 1,"unknown": 0},"byHlrStatus": {"ACTIVE": 2,"ABSENT": 0,"INACTIVE": 0,"INVALID": 0,"UNKNOWN": 1}},"totalCost": {"amount": 0.024,"currency": "USD"},"results": [{"index": 0,"success": true,"reference": "lead-1","msisdn": "0244123456","e164": "233244123456","country": "Ghana","countryCode": "GH","carrier": "MTN","networkType": "mobile","ported": false,"roaming": false,"reachable": true,"hlrStatus": "ACTIVE","mcc": "620","mnc": "01","cost": { "amount": 0.008, "currency": "USD" }},{"index": 1,"success": true,"reference": "lead-2","msisdn": "0209876543","e164": "233209876543","country": "Ghana","countryCode": "GH","carrier": "Telecel","networkType": "mobile","ported": true,"roaming": false,"reachable": true,"hlrStatus": "ACTIVE","mcc": "620","mnc": "02","cost": { "amount": 0.008, "currency": "USD" }},{"index": 2,"success": true,"reference": "lead-3","msisdn": "+233555539152","e164": "233555539152","country": "Ghana","countryCode": "GH","carrier": "Unknown VoIP","networkType": "voip","ported": false,"roaming": false,"reachable": false,"hlrStatus": "UNKNOWN","mcc": null,"mnc": null,"cost": { "amount": 0.008, "currency": "USD" }}],"errors": []}}
Response Shape
| Field | Type | Required | Description |
|---|---|---|---|
| bulkId | string | required | Unique ID for the bulk job (BLK-…). |
| total | number | required | Count of numbers submitted. |
| succeeded | number | required | Rows that completed an HLR query successfully. |
| failed | number | required | Rows that failed validation or HLR. |
| summary | object | required | Aggregates: reachable, ported, byNetworkType, byHlrStatus. |
| totalCost | object | required | Sum of billed costs { amount, currency } for successful rows. |
| results | array | required | Per-number enrichment objects (same fields as single lookup + index, success). |
| errors | array | required | Row-level failures with index, msisdn, code, message. |
Each item in results includes the same HLR fields as single lookup: e164, carrier, networkType, ported, roaming, reachable, hlrStatus, mcc, mnc, cost. Full definitions: Response Fields.
Code Examples
curl -X POST 'https://api.sendexa.co/v1/lookup/bulk' \-H 'Content-Type: application/json' \-H 'Authorization: Basic YOUR_DASHBOARD_TOKEN' \-d '{"defaultCountryCode": "GH","campaignName": "Q3 list clean","numbers": [{ "msisdn": "0244123456", "reference": "lead-1" },{ "msisdn": "0209876543", "reference": "lead-2" },{ "msisdn": "0555539152", "reference": "lead-3" }]}'
HTTP Status Codes
| Code | Status | Description |
|---|---|---|
| 200 | OK | Batch finished (full or partial success). Inspect succeeded/failed. |
| 400 | Bad Request | Empty list, over 1000 numbers, or invalid schema |
| 401 | Unauthorized | Missing or invalid Basic Auth token |
| 403 | Forbidden | Insufficient credits for estimated batch cost |
| 429 | Too Many Requests | Bulk rate limit exceeded (10 requests/second) |
API Error Codes
| Code | Scope | Cause |
|---|---|---|
BULK_LIMIT_EXCEEDED | Request | More than 1000 entries in numbers |
INVALID_MSISDN | Row | That row’s msisdn failed validation |
INVALID_COUNTRY_CODE | Request/Row | defaultCountryCode or row countryCode invalid |
INSUFFICIENT_CREDITS | Request | Balance cannot cover estimated successful rows |
LOOKUP_FAILED | Row | Upstream HLR error for that index |
RATE_LIMIT_EXCEEDED | Request | Too many bulk requests per second |
Common Use Cases
Pre-campaign list clean
Drop INVALID / unreachable / VoIP numbers before bulk SMS to save credits.
Carrier mix reports
Use summary.byNetworkType and per-row carrier to plan routing spend.
Batch onboarding screen
Flag ported or VoIP numbers in imported CRM lists before account activation.
Best Practices for Bulk
Do
- ✓ Chunk lists into batches of ≤ 1,000
- ✓ Set defaultCountryCode for national-format lists
- ✓ Attach reference IDs for CRM reconciliation
- ✓ Inspect both results and errors arrays
- ✓ Log bulkId and totalCost for finance
Don't
- ✗ Loop single lookup for thousands of numbers
- ✗ Assume HTTP 200 means zero row errors
- ✗ Ignore INSUFFICIENT_CREDITS mid-campaign
- ✗ Resubmit identical full batches without caching
- ✗ Omit timeouts (use ≥ 60s client timeout)
Related docs
- Single Lookup — detailed field semantics shared with bulk results
- Response Fields — complete enum and type reference
- Getting Started — auth and number formatting