DID monitoring API
DID monitoring API lets you submit your numbers once. We recheck them on a schedule and alert you by email and by webhook when one is flagged.
How a check works
Send the numbers in one request. Each new number starts as pending and gets its first check within minutes for a small list. A large upload takes longer, because checks run in batches.
After that, we recheck the list on the schedule you set. You do not poll us for every number. When a number becomes flagged, or a flagged number comes back clean, we email you and post a webhook.
What you see
A number is pending, clean, flagged, or unknown. Pending means it is waiting for the first check. Clean means the last check found no spam or scam flag. Flagged means it did, and the label is Spam or scam risk. Unknown means the last check could not finish, so it runs again on the next pass.
Number age alone never flags a number. The response is the verdict and that label. It does not include a score or a per-check breakdown.
Submit numbers
POST /api/did-monitoring/v1/numbers with the X-Auth header. A list created this way is checked once a day. You can change that schedule. Each check costs 1 credit and is charged before it runs, including a check that ends as unknown. Reads and webhooks are included.
curl -s -X POST \
-H "X-Auth: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"numbers":["+15550100123"],"default_country":"US"}' \
https://callerapi.com/api/did-monitoring/v1/numbers
{
"status": "success",
"data": {
"added": 1,
"duplicates": 0,
"invalid": [],
"monitoring": {
"state": "scheduled",
"schedule": "Every 24 hours",
"next_check_at": "2026-10-30T00:00:00Z"
}
}
}
Read status and remove a number
GET /api/did-monitoring/v1/numbers lists the account. Filter with status=flagged and page with limit and cursor. This read does not run a check. DELETE /api/did-monitoring/v1/numbers/+15550100123 removes one number. GET with the same path returns that one number.
{
"status": "success",
"data": {
"counts": {"total": 1, "flagged": 1, "clean": 0, "pending": 0, "unknown": 0},
"numbers": [
{
"phone": "+15550100123",
"status": "flagged",
"label": "Spam or scam risk",
"status_changed_at": "2026-10-29T08:02:11Z",
"last_checked_at": "2026-10-29T08:02:11Z",
"next_check_at": "2026-10-30T00:00:00Z"
}
],
"next_cursor": null
}
}
Set the check schedule
PUT /api/did-monitoring/v1/schedule. Intervals are 15 or 30 minutes, or 1, 2, 3, 4, 6, 8, 12, or 24 hours. GET on the same path reads the saved schedule. If the monthly checks would cost more than the credits the plan includes, the schedule is saved paused until the plan covers it.
{"enabled": true, "interval_minutes": 1440, "timezone": "UTC"}
{
"status": "success",
"data": {
"state": "scheduled",
"summary": "Every 24 hours",
"next_check_at": "2026-10-30T00:00:00Z",
"enabled": true,
"interval_minutes": 1440,
"timezone": "UTC",
"estimate": {
"numbers": 1,
"credits_per_month": 30,
"included_credits": 5000,
"over_plan": false
}
}
}
Webhook alerts
One webhook per account, except on the free plan. PUT /api/did-monitoring/v1/webhook with an https URL on port 443 or 8443. The secret is shown once, on create or on POST /api/did-monitoring/v1/webhook/rotate-secret. The previous secret keeps signing for 24 hours. GET reads the URL and delivery state and never returns the secret. DELETE removes it. POST /api/did-monitoring/v1/webhook/test sends one signed webhook.test event and returns the status your server gave.
number.flagged fires when a number becomes flagged. number.cleared fires when a flagged number is clean again. A first clean result does not send an event. Turning email off does not stop webhooks. We retry a failed delivery after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, 12 hours, and 24 hours. After that the event is failed. Repeated failures turn the endpoint off, and we email you once.
{
"id": "evt_8f3c2a1e9b7d4c60",
"type": "number.flagged",
"created_at": "2026-10-29T08:02:11Z",
"data": {
"phone": "+15550100123",
"status": "flagged",
"previous_status": "clean",
"label": "Spam or scam risk",
"checked_at": "2026-10-29T08:02:11Z"
}
}
{
"id": "evt_1a7d5e0c3f9b2468",
"type": "number.cleared",
"created_at": "2026-11-02T08:01:47Z",
"data": {
"phone": "+15550100123",
"status": "clean",
"previous_status": "flagged",
"label": "No flags",
"checked_at": "2026-11-02T08:01:47Z"
}
}
Signing
Each POST carries CallerAPI-Event-Id, CallerAPI-Timestamp, and CallerAPI-Signature. The signature is v1= and the hex HMAC SHA256 of the unix timestamp, a dot, and the raw body, keyed with your endpoint secret. During a rotation the header has two v1= values, separated by a comma. Reject a timestamp older than 5 minutes and compare signatures in constant time. Events can arrive more than once and out of order. Dedupe on id and order by checked_at.
The same account key works on the DID reputation monitoring API page, which explains who this is for. Your plan caps how many numbers you can store at the credits that plan includes.