Bulk skip tracing vs API lookups: which fits?
A batch file and an API call can return the same phone number. What differs is when you get it and how many rows you pay for. Bulk skip tracing sends a whole list out and brings back an appended file, usually hours or days later. A person lookup API answers one record at a time, at the moment your system asks. Teams tend to pick one by habit and then live with the wrong tradeoff for years. The right choice depends on three things: how often new records arrive, how soon you act on the results, and what share of rows you will actually use.
Key takeaways
- Batch suits one-off cleanup of a list you will work within days, before the appended data ages.
- An API suits continuous intake: look up each record when it arrives or when someone is about to act on it.
- A two-step API (search, then open only the profiles you need) charges for the records you use, not every row.
- Whichever you pick, store a lookup date with every appended field so stale data can be aged out.
How batch skip tracing and API lookups differ
| Batch file (bulk upload) | Per-record API | |
|---|---|---|
| Trigger | You export a list and submit it | Your system calls when a record arrives or is about to be worked |
| Turnaround | Minutes to days, depending on the provider and list size | Seconds per record |
| Freshness when you act | Ages from the day the file comes back | Current at the moment of the call |
| What you pay for | Usually every submitted row, match or not | Each lookup, and with a two-step flow only the profiles you open |
| Engineering effort | Low: CSV out, CSV in | Moderate: auth, retries, rate limits, storing results |
| Review of weak matches | Spreadsheet triage after the fact | Inline: route low-confidence results to a queue as they come back |
| Audit trail | One file per run | One logged request per record, with timestamp and purpose |
Neither column is better in general. The cost row is the one teams misjudge: in a hypothetical 50,000-row file where only 15,000 accounts are ever worked, a per-row batch price is paid 50,000 times, while a two-step API opens around 15,000 profiles plus the searches that found them.
Where batch skip tracing works, and where it breaks
Batch is the right tool for a bounded, one-off job. Say a team acquires a portfolio of 20,000 accounts with addresses last confirmed two years ago, and will start working the whole set next week. Sending one file, reviewing the appended results, and loading them back is simpler than writing an integration, and the data will be used before it ages much.
It breaks in three situations:
- Slow use. If the hypothetical team works only 2,000 of those accounts a month, the last tranche gets worked ten months after the append. Phones get reassigned and people move in that time, so the data that looked current at load time is a guess by the time anyone dials.
- Low usage. If only a fraction of rows will ever be worked, paying to append every row is paying for data that goes straight into storage.
- Repeating batches. Re-running the full file monthly to stay fresh multiplies the cost and still leaves gaps between runs.
Where a person lookup API fits
An API fits when records arrive continuously or when the value of the data depends on its age at the moment of use. Typical triggers:
- A new account is placed or a new lead enters the CRM.
- A collector opens an account to work it today.
- A letter is about to be queued for an address that was last confirmed months ago.
The two-step pattern keeps the cost tied to use. A search returns candidate people with match scores; your code opens the full profile only for the candidate it accepts. With CoverFi, a search returns candidates with permanent record IDs and a 0-100 match-confidence score, and opening a full profile (address history, phones, emails, name variants) is a second, separately metered call. A sketch of the pattern, independent of any provider:
def refresh_contact(account):
candidates = search(name=account.name, state=account.state, dob=account.dob)
best = max(candidates, key=lambda c: c.confidence, default=None)
if best is None:
return mark_no_match(account)
if best.confidence < REVIEW_THRESHOLD:
return queue_for_review(account, candidates) # a person decides
profile = open_profile(best.record_id) # pay only for this one
save_contact(account, profile, looked_up_at=now(), purpose=account.purpose)
The skip tracing API guide covers authentication, the two-step flow, and match tiers in more detail. If your inputs are messy, standardize names and addresses before either approach; a poorly formatted batch file fails silently, row by row.
A verdict by situation, plus the rules that apply to both
| Situation | Better fit |
|---|---|
| One-time cleanup of a list you will fully work within weeks | Batch |
| Continuous inflow of new accounts or leads | API at intake |
| Large backlog worked slowly over months | API at the moment of work |
| Data append to a dormant list "just in case" | Neither: look up when you have a reason to contact |
| Mixed: big initial list, then steady inflow | Batch once, then API for new and re-opened records |
Some rules apply whichever you choose, and they belong in the integration spec, not a policy binder: a purpose field on every request, a looked_up_at date on every appended value, and a retention period such as 12 months that your own counsel has approved. Look up only records you have a permitted purpose for. Keep only the fields you need. And remember that a data append is for reaching the right person: CoverFi is not a consumer reporting agency, and its results are not for decisions about credit, employment, insurance, or housing. The developers category collects related posts on integration patterns.
Frequently asked questions
Is bulk skip tracing cheaper than an API?
Per row it can look that way, but batch often charges for every submitted row, while a two-step API charges for the lookups and profiles you use. Compare the cost per record you actually work, not per row submitted.
How fresh is batch skip tracing data?
It is as fresh as the day the file came back and ages from there. If you will work the list over months, refresh records at the moment of use instead.
Can I use both batch and API lookups?
Yes. A common pattern is one batch pass for an existing backlog, then API calls for new and re-opened records so nothing waits for the next batch run.