API Quickstart: Authentication, Sandbox, and Errors
Create an API key, make your first calls, and handle rate limits and the error envelope.
The Acquired Data API lets you run everything the dashboard can do — skip tracing, DNC scrubbing, property pulls, and buyer searches — from your own code. All endpoints live under a single base URL; property data has a newer v2 surface alongside it (same key, same error envelope):
https://www.acquired-data.com/api/v1
https://www.acquired-data.com/api/v2 (property pulls and enrichment)Integrations built against the previous base URL, https://data.acquiredcrm.com/api/v1, continue to work — no migration required. New integrations should use the base URL above.
Create an API key
Go to Dashboard → Webhooks → API Keys and create a key. Keys look like ad_live_... and are shown once, at creation time — copy it into your secrets manager immediately. If you lose a key, revoke it and create a new one. Every request authenticates with a standard bearer header:
Authorization: Bearer ad_live_XXXXAPI usage bills against the same credit balance as the dashboard, at your account's per-operation rates.

Your first two calls
Start with GET /me — it verifies your key and returns your credit balances plus the environment your account is running in:
curl https://www.acquired-data.com/api/v1/me \
-H "Authorization: Bearer ad_live_XXXX"{
"email": "you@company.com",
"credits_balance": 52689,
"monthly_credits": 30000,
"purchased_credits": 22689,
"environment": "production"
}Then fetch GET /pricing. Pricing is per account — custom rates override the platform defaults — so always read your own numbers instead of hardcoding them:
curl https://www.acquired-data.com/api/v1/pricing \
-H "Authorization: Bearer ad_live_XXXX"{
"currency": "credits",
"per_record": {
"base_trace": 1,
"single_trace": 2,
"llc_trust_trace": 6,
"property_pull": 1,
"buyer_profile": 70,
"cached_buyer_profile": 10
},
"add_ons": {
"dnc": 0.5,
"phone_verification": 0,
"litigator": 0.5,
"deceased": 0,
"tested_emails": 0.1,
"data_verification": 0.9,
"family_contacts": 1,
"verified_contact": 1,
"property_valuation": 0,
"property_liens": 0
},
"property_data": {
"credit_per_record": 1,
"free_records_per_period": 30000,
"free_records_remaining": 27410,
"period_end": "2026-11-03T00:00:00Z"
},
"notes": "Costs are per record, in credits. LLC/Trust-owned records bill at llc_trust_trace instead of base_trace; trace add-ons are charged per record on top. Property pulls and enrichment are 1 credit per record with every dataset included; subscribers' plan credits double as free records each period."
}Property data is the one flat rate: property_pull is always 1 credit per record with everything included, and the property_data block reports how many free records your subscription still has this period (see property pulls and enrichment).
Sandbox vs. production
The environment field on /me (and on every job response) tells you which mode your account is in. In sandbox, requests return realistic sample data and never bill credits — ideal for wiring up your integration end to end. In production, every operation runs against live data and charges credits. Contact support to switch your account between environments.
One exception: the property endpoints — POST /api/v1/enrich, POST /api/v2/enrich, and /api/v1/property-pulls / /api/v2/property-pulls — always run live against our own property database and charge credits (or use free records) regardless of the account environment; their responses report environment: "production" even on a sandbox account. Test them with small counts.
Rate limiting
Each key is limited to 60 requests per minute. Exceeding it returns 429 rate_limited with a Retry-After header (seconds until the window resets). Bulk operations run one job of each kind per account at a time. Skip-trace jobs submitted while one is running are queued (up to five, started automatically in order — the 202 says "queued" with a queue_position); once five are waiting, a submission returns 429 queue_full. A synchronous call (single trace) made while a bulk job is running, or a concurrent job of another kind, returns 429 job_in_progress — wait for the running job to resolve, or honor Retry-After.
Error envelope
Every error response uses one consistent envelope:
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits for this job."
}
}| Status | Code | When |
|---|---|---|
| 401 | unauthorized | Missing, malformed, or revoked API key |
| 402 | insufficient_credits | Not enough credits — top up in Billing |
| 403 | lockdown | Platform temporarily locked by an administrator |
| 404 | not_found | Resource doesn't exist or belongs to another account |
| 409 | job_not_complete | Results or a webhook retry requested before the job resolved |
| 422 | validation_error | Bad request body — the message lists the offending fields |
| 429 | job_in_progress | A synchronous call was made while a bulk job is running on this account — retry after Retry-After |
| 429 | queue_full | Already 5 bulk jobs waiting on this account — retry after Retry-After |
| 429 | rate_limited | Over 60 requests/minute on this key — retry after Retry-After |
| 500 | internal_error | Unexpected failure — safe to retry |
Endpoint index
| Endpoint | What it does |
|---|---|
GET /v1/me · GET /v1/pricing | Account snapshot and your live per-record rates. |
POST /v1/trace · POST /v1/jobs · GET /v1/jobs/{id} | Single and bulk skip tracing, with results and completion webhooks. |
POST /v1/dnc-jobs · POST /v1/phone-scrubs | DNC/TCPA scrubbing of traced rows, and of phone numbers you already have. |
POST /v2/property-pulls · POST /v2/property-pulls/count | Pull filtered property lists from the property database; count matches for free first. |
GET /v2/property-pulls · GET /v2/property-pulls/{id} · GET /v2/property-pulls/{id}/results | List pulls, check one, and page through its records as JSON. |
GET /v2/property-pulls/quota · GET /v2/property-pulls/list-stacks | Your free-record allowance this period, and the List Stack slugs you can filter by. |
POST /v2/enrich | Full property record for a single address. |
POST /v1/property-pulls · POST /v1/enrich | Backward-compatible v1 property endpoints (same bodies, now 1 credit per record). |
POST /v1/buyers | Likely buyers for a property address. |
Next steps
- Single skip traces — synchronous one-off lookups with
POST /trace. - Bulk jobs — up to 10,000 rows per job as JSON or CSV.
- DNC scrubbing — compliance-scrub lists you already own.
- Property pulls and enrichment — the v2 filters object, free match counts, quota, and single-address enrichment at 1 credit per record.
- Buyer search — find likely buyers around any address.
- Webhooks — signed completion callbacks for async jobs.
Keep reading
API: Single Skip Trace
Look up one owner synchronously with POST /trace and get contact data back inline.
Read →APIAPI: Bulk Skip-Trace Jobs
Submit up to 10,000 rows as JSON or CSV, poll status, and fetch paginated results.
Read →APIAPI: DNC Scrubbing Jobs
Compliance-scrub lists with DNC and phone verification always on via /dnc-jobs.
Read →