API Version 1.0 (REST + JSON Lines / CSV)

UniDataHub Business Data API

Integrate fresh, high-intent business records directly into your CRM, lead enrichment pipeline, or SaaS platform. Submit asynchronous extraction jobs, poll progress, and retrieve structured results on demand.

cURL Example
curl -X POST https://unidatahub.com/api/v1/jobs \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "queries": [
      "dentists in Boston, MA",
      "pediatricians in Cambridge, MA"
    ],
    "depth": 20,
    "email": true,
    "json": false
  }'
Response: 202 Accepted Cost: 1 credit / query
01

Submit Job

Send a batch of up to 100 search queries with scraper parameters (depth, email, json, zoom). Credits are deducted atomically.

02

Asynchronous Polling

Scraping runs on isolated cloud compute. Poll GET /api/v1/jobs/{jobId} every 3 to 5 seconds until the status reaches COMPLETED or FAILED.

03

Stream Results

Retrieve structured business listings formatted either as standard sanitized UTF-8 CSV or high-efficiency JSON Lines (one JSON object per line).

Secure Server-Side Gateway Architecture UniDataHub's public API operates through a secure, authenticated server-side gateway. Each developer uses their own cryptographically generated API key. All upstream infrastructure tokens are securely protected on the server side and never leaked to browser code or client responses. Store your API key strictly in server-side environment variables or secret vaults.

Supported Scraper Options

Configurable parameters supported by our data extraction engine.

Parameter Type Default Allowed Range / Format Description
queries array of string Required 1 – 100 items (max 300 chars each) List of localized search query phrases (e.g. "coffee shops in Seattle, WA").
depth integer 20 1 – 100 Maximum listing depth to scrape per query.
email boolean false true / false When true, enables deep contact enrichment to extract business emails from websites.
json boolean false true / false When true, results are delivered as JSON Lines (.jsonl) instead of CSV.
lang string "en" ISO language code ("en", "es", "de", "hi") Localization language code for listing titles and review fields.
zoom integer 15 0 – 21 Map zoom viewport level for geospatial radius bounding.
geo string null "latitude,longitude" Optional center coordinates for localized boundary scraping (e.g. "37.7749,-122.4194").

Endpoint Reference

Base URL: https://unidatahub.com/api/v1

POST /api/v1/jobs
Rate Limit: 20 jobs/hr

Submit an asynchronous batch extraction job. Deducts 1 credit per query from your shared account balance. Returns a 202 Accepted response with the new job_id.

Request Body (JSON)
{
  "queries": [
    "real estate agents in Austin, TX",
    "property managers in Austin, TX"
  ],
  "depth": 25,
  "email": true,
  "json": false
}
Response (202 Accepted)
{
  "success": true,
  "job_id": "671e3b8a1c9d2f0012ab34cd",
  "status": "QUEUED",
  "query_count": 2,
  "credits_used": 2,
  "credit_balance": 48,
  "format": "csv",
  "status_url": "/api/v1/jobs/671e3b8a1c9d2f0012ab34cd",
  "results_url": "/api/v1/jobs/671e3b8a1c9d2f0012ab34cd/results"
}
GET /api/v1/jobs/{jobId}
Polled Status

Check the current status and metadata of a submitted job. Terminal statuses are COMPLETED and FAILED.

Response (200 OK)
{
  "job_id": "671e3b8a1c9d2f0012ab34cd",
  "status": "COMPLETED",
  "query_count": 2,
  "row_count": 142,
  "format": "csv",
  "credits_used": 2,
  "results_ready": true,
  "download_url": "/api/v1/jobs/671e3b8a1c9d2f0012ab34cd/results/download",
  "created_at": "2026-10-24T18:22:10Z",
  "updated_at": "2026-10-24T18:24:35Z"
}
GET /api/v1/jobs/{jobId}/results
Download Descriptor / Direct Stream

Returns the secure download descriptor for a completed job. Pass ?download=true to stream the data file directly. If called while the job is still running, returns 409 Conflict.

JSON Response (Default)
{
  "job_id": "671e3b8a1c9d2f0012ab34cd",
  "status": "COMPLETED",
  "format": "csv",
  "row_count": 142,
  "filename": "unidatahub_job_671e3b8a1c9d2f0012ab34cd.csv",
  "download_url": "/api/v1/jobs/671e3b8a1c9d2f0012ab34cd/results/download",
  "expires_in_seconds": 900
}

Complete Client Implementation Examples

import time
import requests

API_BASE = "https://unidatahub.com/api/v1"
API_KEY = "YOUR_API_KEY"  # Replace with key generated in Developer Dashboard

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

# 1. Submit extraction job
submit_payload = {
    "queries": [
        "accountants in Dallas, TX",
        "tax consultants in Dallas, TX",
    ],
    "depth": 20,
    "email": True,
    "json": False,  # True for JSON Lines, False for CSV
}

resp = requests.post(f"{API_BASE}/jobs", json=submit_payload, headers=headers)
resp.raise_for_status()
job = resp.json()
job_id = job["job_id"]
print(f"Submitted Job ID: {job_id}. Polling status...")

# 2. Poll until terminal status with exponential backoff
backoff = 3.0
max_timeout_seconds = 600
start_time = time.time()

while time.time() - start_time < max_timeout_seconds:
    status_resp = requests.get(f"{API_BASE}/jobs/{job_id}", headers=headers)
    status_data = status_resp.json()
    status = status_data.get("status")

    if status == "COMPLETED":
        print(f"Extraction succeeded! Extracted {status_data.get('row_count')} records.")
        break
    elif status == "FAILED":
        raise RuntimeError(f"Job failed: {status_data.get('error')}")

    time.sleep(backoff)
    backoff = min(backoff * 1.25, 10.0)

# 3. Stream download results file
download_url = f"{API_BASE}/jobs/{job_id}/results/download"
with requests.get(download_url, headers=headers, stream=True) as dl_resp:
    dl_resp.raise_for_status()
    with open("results.csv", "wb") as f:
        for chunk in dl_resp.iter_content(chunk_size=65536):
            if chunk:
                f.write(chunk)

print("Downloaded results successfully to results.csv.")

HTTP Status & Error Responses

Status Code Name Description & Remediation
202 Accepted Job accepted into queue. Save job_id and poll the status endpoint.
200 OK Request succeeded. Status or download descriptor returned.
400 Bad Request Invalid payload, empty query list, or option exceeding maximum boundaries (e.g. depth > 100).
401 Unauthorized Missing, malformed, or revoked API key. Verify key in Developer Dashboard.
402 Payment Required Insufficient account credits to cover the query count. Recharge credits in your dashboard.
404 Not Found The specified job_id does not exist or belongs to another user account.
409 Conflict Results requested before job has completed. Continue polling status until COMPLETED.
429 Too Many Requests Rate limit exceeded (standard tier: 20 jobs/hour). Back off and retry.
502 Bad Gateway Temporary upstream error. Any deducted credits are automatically refunded to your balance.

Ready to Integrate Fresh Business Data?

Get started today with 5 free credits on signup. Generate individual keys, automate extraction pipelines, and scale effortlessly.