Quick start
Base URL: https://dnc.2.24.112.83.sslip.io. Every lookup needs an API key in the Authorization header.
curl "https://dnc.2.24.112.83.sslip.io/api/v1/check?phone=555-234-4567" \
-H "Authorization: Bearer YOUR_API_KEY"
Authentication
Send Authorization: Bearer YOUR_API_KEY (or X-API-Key: YOUR_API_KEY). Missing or wrong keys get 401. Keep keys server-side; don't ship them in a browser or mobile app.
Endpoints
GET /api/v1/check?phone=…
Single lookup. Several numbers can be comma separated (?phone=5552344567,5557654321) or repeated (?phone=…&phone=…).
POST /api/v1/check — JSON
// single
{ "phone": "(555) 234-4567" }
// bulk (up to 1,000)
{ "phones": ["5552344567", "+1 555 765 4321", "555.222.3333"] }
A bare JSON array (["555…", "555…"]) also works.
POST /api/v1/check — CSV / plain text
Send Content-Type: text/csv with one number per line. Only the first column of each line is read, and header rows are skipped, so most contact exports work as-is if the phone is the first column.
curl -X POST "https://dnc.2.24.112.83.sslip.io/api/v1/check?format=csv" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: text/csv" \
--data-binary @phones.csv -o dnc-results.csv
CSV output
Add ?format=csv (or Accept: text/csv) to any request to get a CSV back with columns input,phone,status,onDnc,source,checkedAt,error.
GET /api/openapi.json · /health
OpenAPI 3 spec (import into Postman, Insomnia, or code generators) and an unauthenticated liveness check.
Phone formats
Any US/Canada (NANP) formatting is accepted: 5552344567, (555) 234-4567, 555.234.4567, +1 555 234 4567, 15552344567. Everything except digits is stripped and a leading country code 1 is dropped. Anything that doesn't end up as a valid 10-digit number comes back as invalid. Duplicates are only looked up once, and results always come back in the same order you sent them.
Response
{
"result": { // only when you sent exactly one number
"input": "(555) 234-4567",
"phone": "5552344567",
"status": "dnc",
"onDnc": true,
"source": "freednclist",
"checkedAt": "2026-11-05T18:02:11.412Z",
"cached": false
},
"results": [ /* one entry per number you sent, same order */ ],
"summary": { "total": 1, "dnc": 1, "clear": 0, "invalid": 0, "unknown": 0 },
"disclaimer": "Federal Do Not Call registry status only. ..."
}
| status | onDnc | Meaning |
|---|---|---|
| dnc | true | On the federal DNC registry. Do not cold call or text. |
| clear | false | Not on the federal registry. |
| invalid | null | Not a valid 10-digit US number (error: "invalid_number"). |
| unknown | null | The registry lookup failed for this number (error: "lookup_unavailable"). Treat as not cleared and retry later. |
cached: true means the answer came from this service's 30-day cache rather than a fresh lookup; checkedAt is when it was actually looked up.
Limits & timing
- Up to 1,000 numbers per request and 1 MB of body. Split bigger lists into several requests.
- 120 requests per minute per API key (
429withRetry-After: 60beyond that). - A single lookup takes about a second. A fresh bulk request takes roughly 5–30 seconds per 500 numbers; previously seen numbers are instant. Set your client timeout to at least 3 minutes for bulk.
Errors
Errors are JSON: {"error":{"code":"…","message":"…"}}.
| HTTP | code |
|---|---|
| 400 | no_numbers, invalid_json |
| 401 | unauthorized |
| 404 | not_found |
| 413 | too_many_numbers (over 1,000) or body over 1 MB |
| 429 | rate_limited |
| 500 / 503 | internal_error, not_configured |
A provider outage does not fail the request: affected numbers come back as unknown while the rest still resolve.
Code examples
JavaScript / Node
const res = await fetch("https://dnc.2.24.112.83.sslip.io/api/v1/check", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.DNC_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ phones: ["5552344567", "(555) 765-4321"] }),
});
const { results, summary } = await res.json();
const okToCall = results.filter(r => r.status === "clear").map(r => r.phone);
Python
import os, requests
r = requests.post("https://dnc.2.24.112.83.sslip.io/api/v1/check",
headers={"Authorization": f"Bearer {os.environ['DNC_API_KEY']}"},
json={"phones": ["5552344567", "(555) 765-4321"]}, timeout=180)
r.raise_for_status()
for row in r.json()["results"]:
print(row["input"], row["status"])
Compliance note
Results reflect the federal Do Not Call registry only. They do not cover state DNC lists, wireless or reassigned-number databases, TCPA litigator lists, or your own internal do-not-contact records. A clear result is not consent to call or text; unknown should be treated as not cleared.