Ava Data

Skip Tracing API

Skip Tracing API — PI-Grade Data, Pay Per Match, No Order Minimum

One POST to the Ava Data skip trace API: send a last name plus an address, and get verified phones, emails, and — on Deep Search — the related-persons graph back as JSON. Credits are charged only when a match is returned; misses cost nothing.

Get Your API Key → Read the API reference

What is the Ava Data Skip Tracing API?

The Ava Data skip tracing API is a REST endpoint that takes a person's name plus a known address (or city/state) and returns the most current verified contact information on file: phone numbers, email addresses, and — on the Deep Search tier — a relational graph of spouses, siblings, parents, and known associates.

Ava Data's underlying identity graph updates every 24 hours, so the number a lookup returns reflects the most recent state of the record rather than a snapshot taken months ago. That lag — between when a phone goes out of service and when the data behind it catches up — is where wrong-number complaints come from. Refresh cadence is the variable worth asking any skip trace API vendor about, ours included: ask what it is before you ask what it costs.

Authentication is a single bearer token passed in the Authorization header — no OAuth flow, no SDK required. Any HTTP client that can send a POST request can call the API.

Internal links: Contact Enrichment API · Bulk Skip Tracing · Phone Number Lookup API · What is skip tracing? · Relational Mapping

How Do I Integrate Skip Tracing Into My Real Estate App?

To integrate skip tracing into a real estate app, call the Ava Data REST API: generate a key in Settings → API Access, POST the owner's name and the property address to /api/v1/standard-search from your server, and store the phones and emails it returns as JSON. Each match costs 1 credit (2¢) per requested data type, a miss costs nothing, and the limit is 60 requests per minute per key. Whole lists of up to 250,000 records go through the bulk CSV endpoint instead. The quickstart below is that first request.

Two things before the first call: an API key, generated from Settings → API Access (API access is on for every account), and the base URL https://app.avadata.ai/api/v1. Every key is limited to 60 requests per minute, counted across all endpoints. There is no sandbox or test mode — the request below runs against live data. The cheapest real test is GET /api/v1/credits, which is free, followed by one phone-only search at 1 credit, charged only when a match comes back. Run it from a server or a terminal, not a browser: the API sends no CORS headers, and a key in front-end code is exposed to anyone who opens the page. Copy it, swap in your key, and run it.

cURL POST /api/v1/standard-search
curl -X POST https://app.avadata.ai/api/v1/standard-search \
  -H "Authorization: Bearer sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "John",
    "lastName": "Smith",
    "address": "123 Main St",
    "city": "Austin",
    "state": "TX",
    "zip": "78701",
    "dataTypes": [
      "phone",
      "email"
    ]
  }'
200 Response
{
  "success": true,
  "data": {
    "matchFound": true,
    "phones": [
      { "number": "5125551234", "lineType": "Mobile" },
      { "number": "5125550199", "lineType": "Landline" }
    ],
    "emails": ["john.smith@example.com"],
    "name": { "first": "John", "last": "Smith" },
    "addresses": [{ "address": "123 Main St", "city": "Austin", "state": "TX", "zip": "78701" }],
    "matchType": "Individual",
    "creditsCharged": 2
  }
}

The schema requires two fields, lastName and dataTypes, but a search that can run needs more: a name plus a complete address — street and ZIP, or city and state. A request with less returns 400 with code INSUFFICIENT_INPUT, and the credits come back. Field names are camelCase, and the API silently drops ones it doesn't recognize, so a first_name field is ignored rather than rejected. Because a name is required, a lookup is keyed on a person, not on an address by itself; the address fields are there to disambiguate which John Smith you mean. If all you have is a property address, resolve the owner name first — that is what finding the owner of a property is for — or put the addresses in a bulk file, where a row with street, city, state and ZIP can be traced without a name.

dataTypes also sets the price: ["phone"] is 1 credit, ["email"] is 1 credit, ["phone","email"] is 2 — one credit per requested type, charged whenever a match comes back, even if one of the two types is empty. List each type once: the API does not remove duplicates, and a repeated type is charged again. On a match the response also carries name as { first, last }, the matched addresses (each { address, city, state, zip }, plus zip4 when known) and matchType, which is Individual or Household. Every field and every error response is listed in the API reference, generated from the OpenAPI spec.

Get Your API Key →

What the API Returns

  • Standard Search — Phone Only (1 credit / $0.02): The phone numbers on file for the subject, mobile numbers first (up to two), then a landline, then any others, each with a line type when one is known. Ideal for dialers and outbound call campaigns: dial the first number and keep the rest as fallbacks.
  • Standard Search — Phone + Email (2 credits / $0.04): The same phones plus the email addresses on file. Useful for multi-touch sequences that combine calls and email.
  • Deep Search (10 credits / $0.20): The subject's phones, emails and addresses plus the related-persons graph. Each associated person (spouse, sibling, parent, associate) comes back with a relationship label and their own phone numbers. This is the lookup designed for hard-to-reach individuals where the primary phone and email are unreachable — you can often reach decision-makers through a confirmed family member or known associate.

Every response is wrapped as { "success": true, "data": { ... } }. The data object includes a matchFound boolean and a creditsCharged field. If matchFound is false, creditsCharged is 0. Deep Search can also return matchFound: true with creditsCharged: 0: the record it found had no phone, email or related person, so nothing billable came back and nothing is charged.

On Deep Search the subject object carries more than contact points: aliases, age, dob, and deceased and bankruptcy booleans (fields with no value on file are left out, not sent as null), alongside the phones, emails, and addresses arrays. Subject phones are { number, lineType, disconnected } objects — disconnected is a boolean worth filtering on before a number reaches a dialer — emails are plain strings, and addresses are { address, city, state, zip }. Entries in relatedPeople are a narrower object — firstName, lastName, age, deceased, bankruptcy, a relationship label such as Spouse, and their own phones; their emails and addresses arrays are present but come back empty. There are no aliases or dob on that object, so don't code against those two outside subject. The deceased flag is the one worth branching on: it is what separates a skip trace that dead-ends from one that routes the record to an heir conversation instead of another unanswered dial.

One limit, stated plainly: Ava Data is not a consumer reporting agency and this data is not a consumer report under the Fair Credit Reporting Act. These fields exist to locate and contact a person. They may not be used to establish anyone's eligibility for credit, insurance, employment, or housing — those are FCRA-regulated purposes, and section 3 of our Terms of Service bars that use. Section 3 also covers outreach: Ava Data does not screen numbers against do-not-call registries on your behalf, and complying with the TCPA, do-not-call rules and consent requirements is yours. The API response has no do-not-call or consent field.

Pricing — Pay Only for Matches

Lookup typeCreditsPrice per matchReturns
Standard — Phone Only1$0.02The phone numbers on file, mobile first, each with a line type when known
Standard — Phone + Email2$0.04The same phones plus the email addresses on file (2 credits on any match)
Deep Search10$0.20Phones, emails, related persons (spouses, siblings, associates)

Credits are only charged when a match is returned. No match = no charge. See full plan details →

Credits come with the $9/month plan (100 credits included); wallet credit packs are separate one-time purchases used after subscription credits. There is no usage minimum on API calls — if you run zero lookups in a month, you are billed $9 for the plan and nothing else.

Get Your API Key →

How the Skip Tracing API Works

Looking for the reference rather than the overview? The full endpoint documentation — parameters, response fields and error codes for every endpoint — is at the API reference, generated from our OpenAPI spec.

Standard Search is the 1–2 credit lookup described above. Deep Search is the same skip trace request shape against POST /api/v1/deep-search, with two differences: it takes no dataTypes parameter because it always returns everything, and lastName is its only required field. It costs 10 credits ($0.20), charged only when the result includes a phone, an email or a related person. A search that matches too many people returns 400 with code INSUFFICIENT_INPUT and refunds the credits; add a first name, a ZIP, or a city and state.

cURL POST /api/v1/deep-search
curl -X POST https://app.avadata.ai/api/v1/deep-search \
  -H "Authorization: Bearer sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "John",
    "lastName": "Smith",
    "address": "123 Main St",
    "city": "Austin",
    "state": "TX",
    "zip": "78701"
  }'
200 Response (abridged)
{
  "success": true,
  "data": {
    "matchFound": true,
    "subject": {
      "firstName": "John",
      "lastName": "Smith",
      "age": 54,
      "deceased": false,
      "phones": [{ "number": "5125551234", "lineType": "Mobile", "disconnected": false }],
      "emails": ["john.smith@example.com"],
      "addresses": [{ "address": "123 Main St", "city": "Austin", "state": "TX", "zip": "78701" }]
    },
    "relatedPeople": [
      {
        "firstName": "Mary",
        "lastName": "Smith",
        "relationship": "Spouse",
        "phones": [{ "number": "5125550147", "lineType": "Mobile", "disconnected": false }],
        "emails": [],
        "addresses": []
      }
    ],
    "creditsCharged": 10
  }
}
POST /api/v1/standard-search
{
  "firstName": "Jane",
  "lastName": "Doe",
  "address": "742 Evergreen Terrace",
  "city": "Springfield",
  "state": "IL",
  "dataTypes": ["phone", "email"]
}
200 Response
{
  "success": true,
  "data": {
    "matchFound": true,
    "phones": [{ "number": "5555550142", "lineType": "Mobile" }],
    "emails": ["jdoe@example.com"],
    "name": { "first": "Jane", "last": "Doe" },
    "addresses": [{ "address": "742 Evergreen Terrace", "city": "Springfield", "state": "IL", "zip": "62704" }],
    "matchType": "Individual",
    "creditsCharged": 2
  }
}

For Deep Search, use POST /api/v1/deep-search with the same identity fields — Deep Search takes no dataTypes parameter and always returns everything. Its data object carries a subject object plus a relatedPeople array, each element containing the related person's first and last name, relationship, and their own phones.

Bulk processing works through a separate async endpoint: upload a CSV, receive a job ID, poll for status, and download the enriched file with layout=standard when complete. See the Bulk Skip Tracing page for details.

The full reference is public at avadata.ai/docs/, no account needed to read it. To call the API, create an account and generate a key in Settings → API Access.

Building the list through the API

The same key also drives List Builder. GET /api/v1/lists/filters returns every filter value and record column. POST /api/v1/lists/preview counts the properties that match your filters and quotes the cost without charging anything. POST /api/v1/lists pulls the list in the background at 1 credit (2¢) per record pulled: it reserves maxRecords credits up front and releases whatever the pull doesn't use. Reading the records with GET /api/v1/lists/{listId}/records or downloading them as a CSV is free, and POST /api/v1/lists/{listId}/skip-trace traces the whole list at the normal bulk price, returning a bulk jobId.

Two details for production code. POST /api/v1/lists and the list skip trace accept an Idempotency-Key header, so a retried request doesn't pull or charge twice; the search and upload endpoints have no such header. And List Builder has limits of its own: 20 previews a minute and 250 a day per account, and 5 pulls running at once. Every endpoint is in the API reference; signed-in accounts also have the in-app API docs at app.avadata.ai/api-docs.

Skip Trace API Errors, Rate Limits, and What a Miss Costs

A miss is not an error. When no record matches, the skip trace API still returns 200, with matchFound: false and creditsCharged: 0 inside the data object — handle it as a normal outcome, not an exception. Real errors share one envelope — success: false plus a descriptive error string, with a machine-readable code or a field on some of them — and the status code carries the meaning. Many errors have no code, so branch on the status first.

StatusWhat it meansHow to handle it
400Invalid or missing request parameters, or a search that can't run as sent.A missing lastName or dataTypes returns the message Required. Code INSUFFICIENT_INPUT means the input can't be searched: on Standard Search, send a name plus street and ZIP or city and state; on Deep Search, the search matched too many people, so add a first name, ZIP, or city and state. Credits are refunded. Not retryable as sent.
401Missing, invalid, or revoked API key, API access turned off, or account suspended.Check that the header is exactly Authorization: Bearer sk_live_…, then generate a new key in Settings → API Access. If it still fails, email support.
402Insufficient credits for the requested operation.Pause the run and top up. Check your balance before a large batch.
403No active plan, a paused plan, a feature not switched on for the account, or a job that belongs to another account.Code SUBSCRIPTION_REQUIRED: start the $9/month plan. SUBSCRIPTION_PAUSED: resume the plan (resumeAt is the automatic resume time). Not retryable until that changes.
404The requested resource does not exist.Check the jobId you are polling and the path — unknown paths return 404 too. Not retryable.
413Request too large.A JSON body over 1 MB (BODY_TOO_LARGE) or an uploaded file over 100 MB (FILE_TOO_LARGE). Split the file.
429Too many requests — over 60 requests per minute per API key.Wait the number of seconds in the Retry-After header — the body repeats it as retryAfter, with code RATE_LIMITED — then retry. Do not open more connections: the limit follows the key, not the connection.
500Internal server error. Any charged credits are refunded for search endpoints.Retry after a short wait. You are not billed for a failed search.

Not every code reaches every endpoint. 402 appears only where credits are spent — the two searches, the bulk and Digital Matching uploads, POST /api/v1/lists and list skip traces — and each endpoint's own list of codes is in the API reference.

The two worth writing handling for before you go to production are 402 and 429. A 402 stops the run mid-file unless you check your balance first, so call GET /api/v1/credits at the head of a batch and compare data.availableCredits against your worst case — every record matching, at 1, 2, or 10 credits each. A 429 means you are over 60 requests per minute on that key; that ceiling covers every call the key makes, status polls and downloads included, and past it the bulk endpoints are the intended path rather than a faster loop.

Frequently Asked Questions

What data does the API return?

A Standard Search returns the phone numbers on file, mobile numbers first, and — when you request email — the email addresses on file, plus the matched name and addresses. A Deep Search adds the full related-persons graph — spouses, siblings, parents, and known associates — each with their own phone numbers.

What match rate should I expect from the skip trace API?

We do not publish a match-rate figure, and you should be skeptical of any provider that quotes one without showing you the input list behind it — match rate is driven largely by what you send in. Both search endpoints require a last name, and results improve when you pair it with a current mailing address; a scraped file of initials and PO boxes will match at a lower rate than a clean owner file, against any database. What the spec does document is the billing rule: creditsCharged is 0 whenever matchFound is false, and any charged credits are refunded if a search endpoint returns a 500. So the question that actually decides your cost is not what share of records match — it is what a match costs (2¢, 4¢, or 20¢ depending on tier) and what a miss costs (nothing). You are not buying a match rate. You are buying only the matches.

Is there a free tier or trial?

The $9/month plan includes 100 credits — enough for 100 Standard phone-only lookups or 10 Deep Searches. There is no free skip tracing tier, sandbox or test mode: every call runs against live data. The cheapest real test is GET /api/v1/credits (free) and then one phone-only Standard Search (1 credit, charged only on a match), and because you only pay for matches, your risk on a first batch is bounded by the number of records that actually return data. API access is on for every account: generate a key in Settings → API Access.

How does this compare to buying a bulk list?

Two different comparisons, and they are worth keeping separate. Against a pre-built list file, the billing model is the whole argument: you pay for every row in the file, including the records with a disconnected number or an owner who moved two years ago, and you find out which is which only after you dial. The API inverts that — records go in, and credits are charged only for the records that come back with data, so a miss costs nothing instead of costing the same as a match. Against a dedicated skip trace vendor — most of the ones in our skip tracing cost guide also bill per hit — the billing model is a wash and the comparison is simply price per match: the Ava Data skip tracing API is 2¢ for phone only, 4¢ for phone plus email, 20¢ for a Deep Search, with no minimum order. That guide puts every published rate in one table, with the date we pulled those prices from each vendor's pricing page, so you can run the arithmetic against your own list.

How is this different from other skip tracing APIs?

The difference is packaging, not just price. Some skip tracing APIs are sold as a separate developer product, with their own signup and their own pricing plan, so a subscription to the same company's dashboard does not include API access. Ava Data's API is not a second product: it is the same account, the same login, and the same credit balance the web app uses, billed at the same published per-match rates — 2¢ per match, 4¢ for phone plus email, 20¢ for a Deep Search — on the same $9/month plan, with no usage minimum on calls. A single lookup is a valid month. Keys are generated from Settings → API Access; API access is on for every account. We will not characterize anyone else's data quality here — for published prices and the date they were sourced, see our skip tracing cost guide.

What is the rate limit on the skip trace API?

60 requests per minute per API key, counted across every endpoint rather than per endpoint, in a fixed 60-second window that starts with the key's first request. Past that the call returns 429 with code RATE_LIMITED and a Retry-After header giving the whole seconds until the window resets. The body repeats that number as retryAfter, alongside limit and resetsAt, and the error message says how long to wait. Wait that long instead of opening more connections, since the limit follows the key. Every response to a request whose key is accepted also carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, so a worker can slow down before it hits the limit; counts are kept per server instance, so treat X-RateLimit-Remaining as a guide and always honor Retry-After.

To move more volume than 60 synchronous calls a minute can carry, the asynchronous bulk CSV path is the intended route for Standard Search work: POST /api/v1/bulk/upload as multipart/form-data with a file (CSV, header row required) and a dataTypes field such as ["phone","email"], then poll GET /api/v1/bulk/{jobId}/status and pull the results from GET /api/v1/bulk/{jobId}/download?layout=standard — the standard result columns, as JSON by default or as a CSV with &format=csv. Each row needs a first and last name with a ZIP or a city and state, or a full street address with city, state and ZIP. Deep Search has no bulk equivalent, so high-volume Deep Search runs pace themselves against the same 60-per-minute limit. See Bulk Skip Tracing for the full flow and the API reference for every error code.

Does Ava Data publish public API documentation?

Ava Data publishes the full OpenAPI 3.0 specification at avadata.ai/openapi.json and the generated reference at avadata.ai/docs/. Both are public and need no account or sales call to read. The spec is synced from the live API at every build and the reference is generated from it, so the documented endpoints follow the live ones, and a client generator pointed at the spec produces a typed SDK.

Is the skip tracing API usage-based?

Billing is usage-based rather than seat- or tier-based: Ava Data charges per requested data type per match, at 1 credit (2¢) for phone only, 2 credits (4¢) for phone plus email, and 10 credits (20¢) for a Deep Search that returns contact data, with nothing charged for a search that returns no match. Every account, including an API account, is on the $9/month plan, which includes 100 credits; API access is included on every account.

Where the API fits in an investor workflow

The API is the data layer under whatever acquisition strategy you run. Building a subject-to pipeline means skip tracing pre-foreclosure lists before the auction date. Gator lenders use single Deep Searches to verify the parties on a contract before funding an EMD. Driving-for-dollars routes produce address lists that become call lists only after you find the owner of each property and run a trace. Whatever the method, the workflow is the same: list in, verified phones out, dial.

Ready to integrate?

Create your account, generate a key in Settings, and send your first request.

Get API Access →