Overview

Reference

API Documentation

Programmatic access to skip tracing and list management over HTTPS.

REST APIStandard JSON over HTTPS
Key authX-API-Key header on every request
WebhooksPush notifications on job completion

Base URL

https://fred.titanskip.com/v1

Authentication

X-API-Key header
curl https://api.titanskip.com/v1/traces \
  -H "X-API-Key: tsk_live_your_key_here" \
  -H "Content-Type: application/json"

Never expose your key in client-side code. Keep it secret and secure to prevent unauthorized access. Rotate keys immediately if you suspect compromise.

Get account info

GEThttps://fred.titanskip.com/v1/account1,200 / hour

Returns the authenticated user's account info: credits balance, billing mode, and subscription/metered state. Use this to show a 'credits remaining' indicator or to pre-flight a submission before calling POST /traces.

ParameterTypeRequiredDescription
Request body
GET /account
Response
{
  "id": "9fa9e14b-6187-473c-8b5f-0b097823886f",
  "email": "[email protected]",
  "billing_mode": "prepaid",
  "credits": 12450,
  "subscription": {
    "plan_id": "starter_v1",
    "plan_name": "Starter",
    "credits_limit": 25000,
    "credits_used": 12550,
    "current_period_end": "2026-06-01T00: 00: 00.000Z"
  },
  "metered": null
}

Get pricing

GEThttps://fred.titanskip.com/v1/pricing1,200 / hour

Returns the current per-row credit rates for each job type. Rates can change — always fetch before computing cost estimates client-side. Rates are global; they do not vary per API key.

ParameterTypeRequiredDescription
Request body
GET /pricing
Response
{
  "rates": {
    "normal": 1,
    "enhanced": 2,
    "llc": 3,
    "dnc": 1
  }
}

List trace jobs

GEThttps://fred.titanskip.com/v1/traces600 / hour

Returns a paginated list of trace jobs for the authenticated user. Includes pagination metadata and a downloadable CSV URL for each trace.

ParameterTypeRequiredDescription
pageintegeroptionalPage number to fetch. Default: 1.
limitintegeroptionalRecords per page. Default: 10. Maximum: 100.
Request body
GET /traces?page=1&limit=10
Response
{
  "_metadata": {
    "page": 1,
    "per_page": 10,
    "page_count": 3,
    "total_count": 24
  },
  "traces": [
    {
      "id": "6a8b8f7a-3d44-4c55-a1d0-53c5bb19d0df",
      "user_id": "9fa9e14b-6187-473c-8b5f-0b097823886f",
      "status": "completed",
      "amount": 249,
      "columns": {
        "first_name": "First Name",
        "last_name": "Last Name",
        "address": "Property Address",
        "city": "Property City",
        "state": "Property State",
        "zip": "Property Zip",
        "mailing_address": "Mailing Address",
        "mailing_city": "Mailing City",
        "mailing_state": "Mailing State",
        "mailing_zip": "Mailing Zip"
      },
      "download_url": "https://csvs.titanskip.com/completed/6a8b8f7a-3d44-4c55-a1d0-53c5bb19d0df.csv",
      "time_start": "2026-03-17T16: 00: 00.000Z",
      "time_end": "2026-03-17T16: 03: 42.000Z"
    }
  ]
}

Create a trace job

POSThttps://fred.titanskip.com/v1/traces60 / hour

Uploads a CSV file for skip tracing, validates required column mappings, deducts credits based on CSV line count minus the header row, sends the file to the tracing provider, and creates a running trace job.

ParameterTypeRequiredDescription
filefilerequiredCSV file upload containing the records to trace.
first_namestringrequiredCSV column name for the owner's first name OR the full company name when the row is an LLC / business.
last_namestringoptionalCSV column name for the owner's last name. Leave blank for company / LLC rows — `first_name` already holds the full business name.
addressstringrequiredCSV column name that contains property street address.
citystringrequiredCSV column name that contains property city.
statestringrequiredCSV column name that contains property state.
zipstringrequiredCSV column name that contains property zip / postal code.
mailing_addressstringoptionalCSV column name for mailing street. Only needed when the mailing address differs from the property address (e.g. absentee owners). For most company rows the business address is the only address — skip this whole mailing block.
mailing_citystringoptionalCSV column name for mailing city. Required when `mailing_address` is provided.
mailing_statestringoptionalCSV column name for mailing state. Required when `mailing_address` is provided.
mailing_zipstringoptionalCSV column name for mailing zip / postal code. Required when `mailing_address` is provided.
modestringoptionalTrace mode: `normal` (default) or `enhanced`. See pricing for per-mode rates.
include_llcsbooleanoptionalIn `normal` mode, also trace company / LLC rows at the LLC rate as a parallel sub-job. Default: `false`.
Request body
POST /traces
Content-Type: multipart/form-data

file: owners.csv
first_name: First Name
last_name: Last Name
address: Property Address
city: Property City
state: Property State
zip: Property Zip
mailing_address: Mailing Address
mailing_city: Mailing City
mailing_state: Mailing State
mailing_zip: Mailing Zip
mode: normal
include_llcs: true
Response
{
  "success": true,
  "id": "6a8b8f7a-3d44-4c55-a1d0-53c5bb19d0df",
  "cost": 249,
  "mode": "normal",
  "include_llcs": true,
  "columns": {
    "first_name": "First Name",
    "last_name": "Last Name",
    "address": "Property Address",
    "city": "Property City",
    "state": "Property State",
    "zip": "Property Zip",
    "mailing_address": "Mailing Address",
    "mailing_city": "Mailing City",
    "mailing_state": "Mailing State",
    "mailing_zip": "Mailing Zip"
  }
}

Single record trace (synchronous)

POSThttps://fred.titanskip.com/v1/traces/single600 / hour

Skip-trace a single record and get the result back inline — no CSV, no job, no webhook. Charges 1 credit at the normal rate (or the LLC rate if `is_entity` is true). Use for one-off lookups or manual research from your own app.

ParameterTypeRequiredDescription
first_namestringrequiredOwner first name, OR full company / LLC name (e.g. "ACME Holdings LLC").
last_namestringoptionalOwner last name. Leave blank for companies.
addressstringrequiredProperty street address.
citystringrequiredProperty city.
statestringrequiredProperty state (2-letter code).
zipstringrequiredProperty zip / postal code.
mailing_addressstringoptionalMailing street address. Optional but improves match quality.
mailing_citystringoptionalMailing city. Required if `mailing_address` is set.
mailing_statestringoptionalMailing state. Required if `mailing_address` is set.
mailing_zipstringoptionalMailing zip. Required if `mailing_address` is set.
is_entitybooleanoptionalForce LLC pricing. Auto-detected if `first_name` contains a company suffix (LLC, INC, CORP, TRUST, etc.). Default: `false`.
Request body
POST /traces/single
Content-Type: application/json

{
  "first_name": "Jordan",
  "last_name": "Reeves",
  "address": "1842 Oak Ridge Dr",
  "city": "Phoenix",
  "state": "AZ",
  "zip": "85032"
}
Response
{
  "matched": true,
  "first_name": "Jordan",
  "last_name": "Reeves",
  "phones": [
    { "number": "+1 (602) 555-0182", "type": "mobile" },
    { "number": "+1 (480) 555-9921", "type": "landline" }
  ],
  "emails": [
    { "address": "[email protected]" }
  ],
  "credits": 1,
  "is_entity": false
}

Get a trace job

GEThttps://fred.titanskip.com/v1/traces/:id1,200 / hour

Returns a single trace job by ID for the authenticated user, including its parsed column mapping and completed CSV download URL.

ParameterTypeRequiredDescription
idstringrequiredTrace job ID.
Request body
GET /traces/6a8b8f7a-3d44-4c55-a1d0-53c5bb19d0df
Response
{
  "id": "6a8b8f7a-3d44-4c55-a1d0-53c5bb19d0df",
  "user_id": "9fa9e14b-6187-473c-8b5f-0b097823886f",
  "status": "completed",
  "amount": 249,
  "mode": "normal",
  "include_llcs": true,
  "columns": {
    "first_name": "First Name",
    "last_name": "Last Name",
    "address": "Property Address",
    "city": "Property City",
    "state": "Property State",
    "zip": "Property Zip",
    "mailing_address": "Mailing Address",
    "mailing_city": "Mailing City",
    "mailing_state": "Mailing State",
    "mailing_zip": "Mailing Zip"
  },
  "worker_id": "queue_abc123xyz",
  "download_url": "https://csvs.titanskip.com/completed/6a8b8f7a-3d44-4c55-a1d0-53c5bb19d0df.csv"
}

List DNC jobs

GEThttps://fred.titanskip.com/v1/dnc600 / hour

Returns a paginated list of DNC + TCPA jobs for the authenticated user. Each job represents one uploaded phone list scrubbed against the Do Not Call registry and the TCPA litigator list.

ParameterTypeRequiredDescription
pageintegeroptionalPage number to fetch. Default: 1.
limitintegeroptionalRecords per page. Default: 10. Maximum: 100.
Request body
GET /dnc?page=1&limit=10
Response
{
  "_metadata": {
    "page": 1,
    "per_page": 10,
    "page_count": 2,
    "total_count": 14
  },
  "jobs": [
    {
      "id": "dnc_19568a12b3c7d4e8f5a6b7c8d9e",
      "name": "Lead list - May 20 2026",
      "status": "completed",
      "total_rows": 5000,
      "match_count": 4980,
      "error_count": 20,
      "credits_charged": 5000,
      "credits_refunded": 20,
      "download_url": "https://api.titanskip.com/v1/dnc/dnc_19568a12b3c7d4e8f5a6b7c8d9e/download",
      "created_at": "2026-05-20T14: 30: 00.000Z",
      "completed_at": "2026-05-20T14: 33: 12.000Z"
    }
  ]
}

Create a DNC job

POSThttps://fred.titanskip.com/v1/dnc60 / hour

Uploads a CSV containing phone numbers and scrubs them against the Do Not Call registry and the TCPA litigator list. Billed per phone at the dnc rate (see GET /pricing). Returns immediately with the new job ID — completion is asynchronous (webhook or poll).

ParameterTypeRequiredDescription
filefilerequiredCSV file containing one phone number per row. Max size: 50 MB.
column_mappingstringrequiredJSON string mapping our 'phone' key to your CSV column header — e.g. {"phone":"Phone Number"}. Numbers can be in any format; we normalize before sending upstream.
Request body
POST /dnc
Content-Type: multipart/form-data

file=phones.csv
column_mapping={"phone": "Phone Number"}
Response
{
  "id": "dnc_19568a12b3c7d4e8f5a6b7c8d9e",
  "name": "phones",
  "status": "processing",
  "total_rows": 5000,
  "rate": 1,
  "credits_charged": 5000
}

Get a DNC job

GEThttps://fred.titanskip.com/v1/dnc/:id1,200 / hour

Returns a single DNC job by ID for the authenticated user. The shape matches the webhook payload's data field, so the same parser works for both polling and webhook receipt.

ParameterTypeRequiredDescription
idstringrequiredDNC job ID (prefixed dnc_).
Request body
GET /dnc/dnc_19568a12b3c7d4e8f5a6b7c8d9e
Response
{
  "id": "dnc_19568a12b3c7d4e8f5a6b7c8d9e",
  "status": "completed",
  "total_rows": 5000,
  "match_count": 4980,
  "error_count": 20,
  "rate": 1,
  "credits_charged": 5000,
  "credits_refunded": 20,
  "download_url": "https://api.titanskip.com/v1/dnc/dnc_19568a12b3c7d4e8f5a6b7c8d9e/download",
  "created_at": "2026-05-20T14: 30: 00.000Z",
  "completed_at": "2026-05-20T14: 33: 12.000Z",
  "error_message": null
}

Retry the trace completion webhook

POSThttps://fred.titanskip.com/v1/traces/:id/retry-webhook60 / hour (max 10 per trace)

Requeues a fresh delivery to the webhook URL configured on the API key that created this trace. Useful when your endpoint was down during the original delivery. The trace state is not recomputed and credits are not re-evaluated — only the outbound notification is re-fired.

ParameterTypeRequiredDescription
idstringrequiredTrace ID (in the URL path). Must be a completed or failed trace owned by your API key.
Request body
POST /traces/trc_19568a12b3c7d4e8f5a6b7c8d9e/retry-webhook
Response
{
  "delivery_id": "whd_19568a12b3c7d4e8f5a6b7c8d9e",
  "scheduled_at": "2026-05-20T15: 00: 00.000Z",
  "attempt": 1,
  "max_attempts": 5
}

Retry the DNC completion webhook

POSThttps://fred.titanskip.com/v1/dnc/:id/retry-webhook60 / hour (max 10 per job)

Requeues a fresh delivery to the webhook URL configured on the API key that created this DNC check. Useful when your endpoint was down during the original delivery. The DNC job state is not recomputed and credits are not re-evaluated — only the outbound notification is re-fired.

ParameterTypeRequiredDescription
idstringrequiredDNC job ID (in the URL path). Must be a completed or failed job owned by your API key.
Request body
POST /dnc/dnc_19568a12b3c7d4e8f5a6b7c8d9e/retry-webhook
Response
{
  "delivery_id": "whd_19568a12b3c7d4e8f5a6b7c8d9e",
  "scheduled_at": "2026-05-20T15: 00: 00.000Z",
  "attempt": 1,
  "max_attempts": 5
}

Completion webhook

POSThttps://fred.titanskip.com/v1(your webhook URL)

We POST to your configured webhook URL when an asynchronous job finalises (a bulk trace or DNC check). Every event uses the same typed envelope — { event, data } — so you can route in a single switch. The `data` field mirrors the exact shape that GET /v1/<type>/:id returns. Single-record traces are synchronous and do not fire webhooks.

ParameterTypeRequiredDescription
X-TitanSkip-SignatureheaderrequiredHMAC-SHA256 of the raw request body, hex-encoded. Signed with the webhook secret from your API Keys page.
X-TitanSkip-Event-IDheaderrequiredUnique ID for this delivery attempt. Dedupe on this for at-most-once handling.
X-TitanSkip-AttemptheaderrequiredAttempt number (1–5). Retries share the resource ID inside `data` as the stable dedupe key.
Request body
// trace.completed (bulk skip trace)
// On trace.failed the same shape is sent with event="trace.failed",
// data.status="failed", download_url=null, and error_message populated.
{
  "event": "trace.completed",
  "data": {
    "id": "trc_19568a12b3c7d4e8f5a6b7c8d9e",
    "status": "completed",
    "mode": "normal",
    "include_llcs": true,
    "total_rows": 23000,
    "match_count": 22000,
    "no_match_count": 800,
    "error_count": 200,
    "credits_charged": 23800,
    "credits_refunded": 1000,
    "download_url": "https://api.titanskip.com/v1/traces/trc_19568a12b3c7d4e8f5a6b7c8d9e/download",
    "created_at": "2026-03-20T14: 30: 00.000Z",
    "completed_at": "2026-03-20T15: 00: 00.000Z",
    "error_message": null
  }
}

// dnc.completed (DNC + TCPA lookup)
// On dnc.failed the same shape is sent with event="dnc.failed",
// data.status="failed", download_url=null, and error_message populated.
{
  "event": "dnc.completed",
  "data": {
    "id": "dnc_19568a12b3c7d4e8f5a6b7c8d9e",
    "status": "completed",
    "total_rows": 5000,
    "match_count": 4980,
    "error_count": 20,
    "rate": 1,
    "credits_charged": 5000,
    "credits_refunded": 20,
    "download_url": "https://api.titanskip.com/v1/dnc/dnc_19568a12b3c7d4e8f5a6b7c8d9e/download",
    "created_at": "2026-03-20T14: 30: 00.000Z",
    "completed_at": "2026-03-20T15: 00: 00.000Z",
    "error_message": null
  }
}
Response
// Reply with any 2xx within 10 seconds.
// Non-2xx triggers up to 5 retries (1s, 5s, 30s, 5min, 30min).
HTTP/1.1 200 OK
Content-Type: application/json

{ "received": true }

Error codes

All errors return error.code and error.message. Validation errors add an error.details array.

CodeNameDescription
400Bad RequestMissing or malformed request parameters. Check the error.details field for field-level messages.
401UnauthorizedMissing or invalid API key. Ensure your X-API-Key header is present and correct.
402Payment RequiredYour account has insufficient credits. Top up your balance to continue making requests.
403ForbiddenYour API key does not have permission to access this resource.
404Not FoundThe requested resource does not exist. Check the ID or path parameter.
422UnprocessableThe request was well-formed but contained semantic errors, such as exceeding the record limit.
429Rate LimitedYou have exceeded your request rate limit. Retry after the duration indicated in the Retry-After header.
500Server ErrorAn unexpected error occurred on our end. These are logged and automatically investigated.
Error response shape
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed.",
    "details": [
      { "field": "records[0].address", "message": "Address is required." },
      { "field": "records[1].last_name", "message": "Last name is required." }
    ]
  }
}