Skip Trace API
The Skip Trace API lets you run skip traces from your own code — any server, script, or third-party tool that can make HTTPS requests. Send an address (and optionally a person or entity name), receive the matched owner records — phones, emails, and names — in the same response. Each call consumes one skip-trace credit from your organization’s balance, the same way an in-app skip trace does.
This is a server-to-server API. Keep your key secret. Never ship it in a browser, mobile app, or any client-side code.
Generating an API key
Section titled “Generating an API key”-
Open the Integrations page. From the left sidebar, click Integrations under the Automations section.
-
Find the Skip Trace API card. It lives under the Developer section. The card is only visible to organization admins — if you do not see it, ask an admin to generate a key for you.
-
Click Generate API key. Goliath shows your new key once, in a dialog. Copy it now and store it in your secrets manager — the full key is never shown again. After you close the dialog, only the first and last characters are visible in the UI.
-
Use the key. Pass it as a Bearer token on every request:
Authorization: Bearer gd_...
Making a request
Section titled “Making a request”Endpoint
Section titled “Endpoint”POST https://api.goliathdata.com/api/v1/skiptraceHeaders
Section titled “Headers”| Header | Value |
|---|---|
Authorization | Bearer gd_... |
Content-Type | application/json |
Example
Section titled “Example”curl -X POST https://api.goliathdata.com/api/v1/skiptrace \ -H "Authorization: Bearer gd_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "address": { "line1": "123 Main St", "city": "Austin", "state": "TX", "zip": "78701" } }'// Node.js (fetch)const res = await fetch("https://api.goliathdata.com/api/v1/skiptrace", { method: "POST", headers: { Authorization: `Bearer ${process.env.GOLIATH_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ address: { line1: "123 Main St", city: "Austin", state: "TX", zip: "78701", }, }),})const data = await res.json()Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
address.line1 | string | yes | Street address. |
address.line2 | string | no | Apartment, unit, suite. |
address.city | string | yes | City name. |
address.state | string (2) | yes | Two-letter USPS state abbreviation (e.g. TX, CA). |
address.zip | string | yes | ZIP code. Five or nine digits. |
actor | object | no | Narrow the trace to a specific person or entity. See below. |
actor.type | person / entity | yes (if actor set) | |
actor.firstName | string | person only | First name. |
actor.lastName | string | person only | Last name. |
actor.name | string | entity only | Entity / company name. |
If actor is omitted, the API traces against whichever owner records are
attached to the property. If actor is provided, results are narrowed to
matches for that specific person or entity.
Response
Section titled “Response”200 OK:
{ "id": "3f21d6e0-a8a4-4a0e-8f25-9e9a74c37c2e", "status": "records_found", "persons": [ { "firstName": "Jane", "lastName": "Doe", "middleName": null, "age": 47, "phones": [ { "number": "5125551234", "type": "mobile" }, { "number": "5125559999", "type": "residential" } ], "emails": ["jane@example.com"] } ]}Fields
Section titled “Fields”| Field | Type |
|---|---|
id | Skip-trace request ID. |
status | records_found or no_records_found. |
persons[].firstName | First name or null. |
persons[].lastName | Last name or null. |
persons[].middleName | Middle name or null. |
persons[].age | Approximate age or null. |
persons[].phones[] | { number, type }. Type is mobile, residential, or unknown. |
persons[].emails[] | Array of email strings. |
A status of no_records_found means the address and actor were valid but
no owner records were located. Credits are still consumed in this case — the
work to look up records has already happened.
Errors
Section titled “Errors”All errors return a JSON body of the shape:
{ "error": { "code": "insufficient_credits", "message": "..." } }| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_key | Missing, malformed, or revoked Bearer key. |
| 402 | insufficient_credits | Your organization has no skip-trace credits. Buy more in the Goliath app. |
| 403 | feature_unavailable | Your organization’s plan or trial does not currently permit skip tracing. |
| 422 | invalid_request | Request body failed validation, or the address could not be resolved. |
| 429 | rate_limited | Too many requests per minute. Back off for Retry-After seconds. |
| 429 | concurrency_limit | Too many in-flight requests from this key at once. |
| 504 | timeout | Skip trace did not complete within 30 seconds. Retry the request. |
| 500 | internal_error | Unexpected server error. Retry; contact support if it persists. |
Rate limits
Section titled “Rate limits”- 1,000 requests per minute per API key.
- 10 concurrent requests per API key per server instance.
Every response includes:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per window (1000). |
X-RateLimit-Remaining | Requests remaining in the current window. |
X-RateLimit-Reset | Unix timestamp when the window resets. |
Retry-After | Seconds to wait. Only set when you receive a 429. |
Credits and billing
Section titled “Credits and billing”Each successful skip-trace call consumes one SKIPTRACE credit from your organization’s balance. This is the same credit pool as in-app skip traces — running either path debits the same bucket.
When your balance hits zero, subsequent calls return 402 insufficient_credits.
Buy more credits in the Goliath app under Billing → Credits and then
retry the request.
Frequently Asked Questions
Section titled “Frequently Asked Questions”Q: How long does a request take?
Section titled “Q: How long does a request take?”Most calls complete in a few seconds. The server will wait up to 30 seconds
for the pipeline to terminate before returning 504 timeout. Retrying a
timed-out request is safe and will return the cached result if one has since
been produced.
Q: Is the result cached?
Section titled “Q: Is the result cached?”Yes. Repeat calls for the same address + actor combination return the cached result from the previous successful trace, without triggering another provider call. Credits are still consumed for each call.
Q: Can I use this from the browser?
Section titled “Q: Can I use this from the browser?”No. API keys are org-level secrets. Anyone with the key can run traces and burn your credits. Keep it on your server and never expose it to client code.
Q: What happens when I rotate the key?
Section titled “Q: What happens when I rotate the key?”The old secret stops working immediately. Any systems still using it start
receiving 401 invalid_key on their next request. Update them with the new
secret before rotating if you can coordinate the switch.
Q: Do you support property IDs as input?
Section titled “Q: Do you support property IDs as input?”No. The public API only accepts street addresses. Property IDs are internal identifiers that change over time and aren’t safe to expose on a stable public surface.