Skip tracing, DNC checks, and property data for U.S. real estate, over a simple JSON API. You pay per hit: a request that finds nothing costs nothing, unless an endpoint says otherwise.
## Get started in 3 steps
1. Get your API key. Log in, then open your account settings from the menu in the top-right corner. No account yet? Create one. Every request sends the key in this header:
Authorization: Bearer YOUR_API_KEY
2. Send your first request. This finds the owner of a property and returns their phones and emails:
bash
curl -X POST https://tracerfy.com/v1/api/trace/lookup/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address": "123 Main St", "city": "Austin", "state": "TX", "zip": "78701"}'
3. Check hit in the response. true means we found data and charged the credits shown in credits_deducted. false means we found nothing and charged nothing.
Every response also carries meta.request_id. Quote it when you contact support.
Try it free: the API Tester runs any endpoint in Mock mode with example data and no credits.
## Authentication, Errors & Rate Limits
Every endpoint requires a Bearer token in the Authorization header: Authorization: Bearer <YOUR_TOKEN>. Requests without a valid token get a 401.
Status codes you may receive:
- 200 OK: success (synchronous endpoints).
- 202 Accepted: async job accepted and queued (e.g. Lead Builder execute).
- 400 Bad Request: malformed body, missing/invalid parameter, or a column named in your request is not present in the uploaded data.
- 401 Unauthorized: missing, malformed, or invalid/expired Bearer token.
- 402 Payment Required: insufficient credits for the requested work.
- 403 Forbidden: account suspended (unpaid invoices or API access disabled), or you tried to access a resource that belongs to another account.
- 404 Not Found: the resource ID does not exist. Lead lists, templates, and monitors also return 404 for an ID that belongs to another account; trace and DNC jobs return 403 for that case.
- 405 Method Not Allowed: wrong HTTP method for the route.
- 409 Conflict: the resource is not ready yet (e.g. reading rows of a lead list that is still processing).
- 429 Too Many Requests: a rate limit was exceeded. Back off and retry; the response body includes how many requests were counted in the window.
- 500 Internal Server Error: an unexpected error. Retry; if it persists, contact support.
- 502 / 503: the request couldn't be completed right away due to a temporary service delay. This usually resolves on its own. If it persists, contact support.
Rate limits (per account):
- Batch Trace: 10 submissions per 5 minutes. An APN Batch Trace is refused while this limit is reached.
- Instant Trace, Enhanced Trace, Phone Verification, APN Instant Lookup & Property Lookup, 500 lookups per minute (shared counter).
- DNC Scrub: 10 scrubs per 5 minutes.
- DNC Instant Lookup: 120 lookups per minute on v2, 30 per minute on v1.
- Fetch all Queues: 1 request per 20 seconds.
- Property Search Preview, Execute & Lookup: 500 property searches per minute.
- Saved Templates & Property Monitors, 60 requests per minute.
- Address & APN Autocomplete: 30 requests per minute.
The insufficient-credits (402) and suspended-account (403) message wording varies slightly per endpoint, but the shape and status code are the same everywhere. Representative bodies are below.
401 Unauthorized: missing or invalid token
json
{
"detail": "Authentication credentials were not provided."
}
400 Bad Request: field validation (detail is a field→messages map)
json
{
"address": [
"This field is required."
],
"state": [
"This field is required."
]
}
402 Payment Required: insufficient credits: When the account cannot use monthly billing
json
{
"error": "Insufficient credits. Instant trace requires 5 credits per lookup. You have 0 credits."
}
402 Payment Required: insufficient credits: When credits are short and no payment method is on file
json
{
"error": "Insufficient credits. Instant trace requires 5 credits per lookup. Please add credits or a payment method."
}
403 Forbidden: account suspended: Unpaid invoices
json
{
"error": "Your account has been temporarily suspended due to unpaid invoices. Please contact
[email protected] to resolve outstanding payments."
}
403 Forbidden: account suspended: API access disabled for this account
json
{
"error": "api_disabled",
"detail": "Your API access has been suspended. Please contact support at
[email protected].",
"status": 403
}
404 Not Found: unknown or cross-account resource ID
json
{
"error": "No Queue Found with ID 123"
}
429 Too Many Requests (rate limited: Most endpoints) includes the count seen in the window
json
{
"status": "429",
"error": "Rate limit exceeded. Max 500 lookups per minute.",
"lookups_in_window": "501",
"retry_after_seconds": "60"
}
429 Too Many Requests: rate limited: Fetch all Queues (20-second throttle)
json
{
"error": "Rate limit exceeded. Retry in intervals of 20 seconds.",
"retry_in": "3 seconds"
}
## Response Metadata
Every response carries an X-Request-Id response header, a unique id Tracerfy assigns to that request. Use it to correlate a specific response with your own application logs and retries, and quote it when contacting support. The id is always assigned server-side; any X-Request-Id you send on the request is ignored.
In addition, every response whose body is a JSON object includes a meta block:
- request_id: the same value as the X-Request-Id header.
- timestamp: when the response was generated (ISO 8601, UTC).
- api_version: the response-schema version that served the request.
meta is additive: new fields may be added over time, so treat unknown keys as optional and ignore them. Endpoints that return a top-level JSON array (e.g. List Trace Jobs and Get One Trace Job) keep their bare-array body and do not include a meta block, read the X-Request-Id header for those. The AI-assist endpoint (/v1/api/property-search/ai-assist/) also returns no meta block (it still carries the X-Request-Id header).
meta block (present on every object response): Example: the Analytics response, with the meta block appended
json
{
"total_queues": 12,
"properties_traced": 18350,
"queues_pending": 2,
"queues_completed": 10,
"balance": 940,
"meta": {
"request_id": "req_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
"timestamp": "2026-07-16T18:22:05Z",
"api_version": "2026-03-21"
}
}
## Sandbox / Testing Environment
Before you spend a single credit, build and test your integration against the free hosted sandbox at https://mock.tracerfy.com. It mirrors this *exact* API (same paths, methods, field names, and response shapes) but returns realistic fake data. Nothing is charged and no credits are consumed.
Going live is a one-line change: develop against https://mock.tracerfy.com/v1/api/, then swap the host to https://tracerfy.com/v1/api/ and use your real token. Nothing else about your code changes.
- Auth: any non-empty Bearer token authenticates, no real key needed. (The reserved value INVALID_TOKEN always returns 401 so you can test your unauthorized path.)
- Deterministic: the same request always returns the same data (it's seeded from your inputs), so your test assertions stay stable. Only meta.request_id and meta.timestamp vary between calls.
- Full coverage: every endpoint in these docs, batch & instant trace, parcel/APN, DNC, property search, saved templates, and property monitors.
- Interactive docs: browse and try every endpoint at https://mock.tracerfy.com/docs.
Magic values: force a specific scenario on demand. Anything you send that isn't a magic value flows through to a normal deterministic fake response. The values below instead trigger a fixed outcome, so you can exercise every branch of your client without hunting for real data that happens to hit or miss:
- Numeric path IDs: use an HTTP status code as any {id} to reproduce that scenario: 404 not found, 403 cross-account, 409 still processing, 0 a pending job. e.g. GET /v1/api/property-monitors/404/ → 404.
- String sentinels: embed a keyword in the primary string field (address, phone, a monitor name, a strategy value, or a CSV *_column): NO_CREDITS→402, SUSPENDED→403, RATE_LIMIT→429, SERVER_ERROR→500, UNAVAILABLE→503, MISSING_COLUMN→400 (CSV), NO_MATCH→200 empty, MULTI→200 multiple results, CAP_REACHED→400 (monitor cap). The literal address 999 Nowhere Blvd behaves as a miss.
The sandbox is for development only: it returns fabricated data, so never point production traffic at it.
bash
# Test against the sandbox: any token works, nothing is billed
curl -X POST 'https://mock.tracerfy.com/v1/api/trace/lookup/' \
-H 'Authorization: Bearer sandbox_test_token' \
-H 'Content-Type: application/json' \
-d '{"address":"123 Main St","city":"Austin","state":"TX","zip":"78701"}'
# Force a scenario with a magic value (402 insufficient credits)
curl -X POST 'https://mock.tracerfy.com/v1/api/trace/lookup/' \
-H 'Authorization: Bearer sandbox_test_token' \
-H 'Content-Type: application/json' \
-d '{"address":"NO_CREDITS","city":"Austin","state":"TX"}'
# Ready for real data? Change the host and use your real token
curl -X POST 'https://tracerfy.com/v1/api/trace/lookup/' \
-H 'Authorization: Bearer <YOUR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{"address":"123 Main St","city":"Austin","state":"TX","zip":"78701"}'
POST /v1/api/trace/lookup/ on the sandbox, the exact body the first curl above returns. Deterministic: the same request always returns this data (only meta varies).
json
{
"address": "123 Main St",
"city": "Austin",
"state": "TX",
"zip": "78701",
"find_owner": true,
"hit": true,
"persons_count": 1,
"credits_deducted": 5,
"persons": [
{
"first_name": "Sandra",
"last_name": "Dean",
"full_name": "Sandra Dean",
"dob": "1958-12",
"age": "67",
"deceased": true,
"property_owner": true,
"litigator": false,
"mailing_address": {
"street": "469 Amy Pines Suite 707",
"city": "Christinebury",
"state": "CT",
"zip": "50627"
},
"phones": [
{
"number": "5088697674",
"type": "Mobile",
"dnc": false,
"tcpa": false,
"carrier": "COMCAST PHONE LLC",
"rank": 1
},
{
"number": "6478388352",
"type": "Landline",
"dnc": true,
"tcpa": false,
"carrier": "US CELLULAR",
"rank": 2
}
],
"emails": [
{
"email": "
[email protected]",
"rank": 1
}
]
}
],
"meta": {
"request_id": "req_b0e2ba54941820e3009e83c0cd14dda6",
"timestamp": "2026-07-20T18:22:05Z",
"api_version": "2026-03-21"
}
}
Magic value NO_CREDITS → 402 (deterministic)
json
{
"error": "Insufficient credits. Lead Builder lookup requires 10 credits per hit. You have 2 credits."
}
Reserved token INVALID_TOKEN → 401
json
{
"detail": "Authentication credentials were not provided."
}
## Connect via AI Assistants (MCP)
Connect Tracerfy to your AI assistant (e.g. Claude) via the Model Context Protocol (MCP) and run skip traces, DNC checks, and lead lists in plain English. Same billing as the API: pay per hit; misses cost nothing.
Generate a personal connector link in your profile under Connect via MCP (https://mcp.tracerfy.com/u/<token>/mcp), the token in the URL authenticates as you, so keep it private. Connect it one of these ways:
- Custom connector: in your AI assistant's connector settings, add a custom connector and paste the link as the server URL, most MCP-capable assistants support this.
- MCP config file (MCP-compatible apps & IDEs): use the JSON below.
- Programmatic API: pass the connector in your request's mcp_servers, full example below (shown for the Claude API).
Example prompts:
- "Skip trace 123 Main St, Phoenix AZ and check the number against Do-Not-Call."
- "How many vacant, high-equity homes are in Dallas?"
- "Build me a list of 500 absentee owners in Miami-Dade."
- "What's my Tracerfy credit balance?"
Available tools:
- start_trace_queue: bulk normal, advanced, or enhanced trace queue from rows
- trace_lookup / enhanced_trace_lookup / parcel_lookup, standard owner contacts by address, enhanced owner or specific-person context, or parcel (APN) lookup
- phone_verification: phone carrier, line type, last-seen, DNC/TCPA flags, and compact associated-person context
- dnc_check: Do-Not-Call / TCPA compliance for a phone
- lead_lookup: full property + owner dossier for an address
- preview_lead_list (free) & execute_lead_list, size and build lead lists
- get_lead_list_status / get_lead_list_rows, track and fetch results
- list_strategies, check_balance: presets/filters and your credits (free)
bash
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: mcp-client-2025-11-20" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Skip trace 123 Main St, Phoenix AZ and check the phone against Do-Not-Call."}
],
"mcp_servers": [
{
"type": "url",
"url": "https://mcp.tracerfy.com/u/<token>/mcp",
"name": "tracerfy"
}
],
"tools": [
{
"type": "mcp_toolset",
"mcp_server_name": "tracerfy"
}
]
}'
TypeScript (Anthropic SDK)
json
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic(); // reads ANTHROPIC_API_KEY
const message = await client.beta.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [
{ role: "user", content: "Skip trace 123 Main St, Phoenix AZ and check the phone against Do-Not-Call." },
],
mcp_servers: [
{ type: "url", url: "https://mcp.tracerfy.com/u/<token>/mcp", name: "tracerfy" },
],
tools: [
{ type: "mcp_toolset", mcp_server_name: "tracerfy" },
],
betas: ["mcp-client-2025-11-20"],
});
console.log(message.content);
MCP config file (Claude Desktop & MCP-compatible clients)
json
{
"mcpServers": {
"tracerfy": {
"url": "https://mcp.tracerfy.com/u/<token>/mcp"
}
}
}