CallCurb Lookup API

Lightweight docs for the app-facing lookup surface

This host exposes a read-only API surface for high-volume phone number reputation lookups. Use HTTPS only, send an API key on lookup requests, and treat the path prefix /v1 as the version contract.

Base URL: https://api.callcurb.com Single lookup: GET /v1/lookup/{e164} Batch lookup: POST /v1/lookup/batch Server sync: GET /v1/spam-report Status: /, /healthz, /metrics

Client Integration Boundary

Allowed client path

Phone apps and partner SDKs must call the HTTPS lookup API at https://api.callcurb.com/v1/*.

Never connect directly to Scylla

App clients must never open direct CQL connections or embed Scylla hostnames or credentials in shipped client code.

Operator-only local verification

The local app-port health check at http://127.0.0.1:3001/healthz is for SSH or on-host deployment verification only, not for mobile-app integration.

Authentication

Lookup requests require an API key. Accepted request forms:

This lightweight service documents and serves lookup and status routes only, and preserves the client boundary that phone apps use HTTPS only and never direct Scylla access.

Single Lookup Example

curl -sS \
  -H "X-API-Key: <your-api-key>" \
  "https://api.callcurb.com/v1/lookup/+14155550100"

The {e164} path parameter must be a strict E.164 phone number such as +14155550100. Missing numbers return 404 NUMBER_NOT_FOUND. Slow or unavailable reads return 503 STORAGE_UNAVAILABLE.

Batch Lookup Example

curl -sS \
  -X POST \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <your-api-key>" \
  -d '{"numbers":["+14155550100","+14155550101"]}' \
  "https://api.callcurb.com/v1/lookup/batch"

Send a JSON body with numbers. The hard limit is 100 E.164 numbers per request. Mixed found and not-found numbers return 200 OK with per-number result objects and meta.partial_success.

Spam Report Sync

GET /v1/spam-report is a protected server-to-server bulk sync endpoint for the PIR shard server. Mobile clients should keep using /v1/lookup/*.

Full snapshot mode

Omit since, pass an optional limit, and keep following next_cursor until it is null.

Daily update mode

Pass since=YYYY-MM-DDTHH:mm:ss.sssZ to fetch rows whose exported fields may have changed, then compare row_hash locally before rebuilding shard data.

Allowlist id

Dedicated keys can allow GET /v1/spam-report without granting other public API endpoints.

Status Endpoints

GET /

Tiny human-facing service summary with build, environment, lookup-store mode, and discoverable route links.

GET /healthz

Liveness health payload for local operator checks and reverse-proxy smoke tests.

GET /metrics

Lightweight JSON metrics with request counts, latency rollups, cache behavior, uptime, and degraded dependency summary.

Response Fields

number

Canonical E.164 phone number that was looked up.

risk_level

Compact top-level published risk label retained for compatibility.

reputation_score

Numeric final score for the number.

confidence

Confidence value associated with the current score.

country / state / city

Geographic fields returned when the lookup row contains verified location data.

categories

Normalized categories currently attached to the number.

report_count_total / report_count_30d

Total and recent abuse-report counters.

registered_business

Safe-business registry truth only. It does not override the published final risk by itself.

abuse_evidence

Recent spoofing, scam, robocall, or corroborated abuse signals.

final_risk

Explicit final risk object with the same published outcome plus scoring metadata.

last_updated

Latest scoring or last-seen timestamp used for the public response.

Error Envelope

Errors return the shared JSON envelope with ok: false, error.code, error.message, top-level code, and requestId.

Common classes for this surface: INVALID_CREDENTIALS, INVALID_INPUT, NUMBER_NOT_FOUND, RATE_LIMIT_EXCEEDED, and STORAGE_UNAVAILABLE.