Skip to main content

Welcome to the CSV Enrichment API

The CSV Enrichment API lets clients submit a list of companies and start the same enrichment workflow available in the Signalbase dashboard. Each company is matched by name, website, or LinkedIn URL, then enriched with company profile data and available signals from Signalbase.

Create CSV Enrichment Job

Submit companies for enrichment

Get CSV Enrichment Job

Poll status and retrieve paginated results

Key Features

  • Company Matching: Match companies by company_name, website_url, or linkedin_url
  • Signal Enrichment: Enrich matched companies with funding, acquisition, hiring, job change, and investor data
  • Dashboard Parity: Uses the same enrichment job pipeline as dashboard CSV enrichment
  • Asynchronous Processing: Returns a job ID immediately while enrichment runs in the background
  • Agent-friendly Retrieval: Poll a free GET endpoint with strict statuses, summary counts, and paginated results
  • Synchronous Small-list Mode: Use wait=true for short lists that should complete in one agent turn
  • Credit-based Usage: Transparent credit consumption per API request

Authentication

All API endpoints require authentication using a Bearer token passed in the Authorization header.
curl -X POST "https://www.trysignalbase.com/api/v2/csv-enrichment" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "companies": [
      {
        "company_name": "Acme",
        "website_url": "https://acme.com",
        "linkedin_url": "https://www.linkedin.com/company/acme"
      }
    ]
  }'

Create Request Body

FieldTypeRequiredDescription
companiesarrayYesCompanies to enrich. Maximum 1,000 companies per request.
fileNamestringNoOptional label stored on the enrichment job. Defaults to api-companies.json.
waitbooleanNoIf true, the API waits up to timeout seconds and returns completed results inline when available. Defaults to false.
timeoutintegerNoMaximum wait time in seconds when wait=true. Minimum 1, maximum 30, default 30.
Each company must include at least one of:
FieldTypeDescription
company_namestringCompany name
website_urlstringCompany website URL or domain
linkedin_urlstringCompany LinkedIn URL
The API also accepts common aliases such as companyName, name, websiteUrl, website, domain, linkedinUrl, linkedin, and company_linkedin_url.

Response Structure

A successful request creates an enrichment job and returns its ID:
{
  "success": true,
  "data": {
    "jobId": "7f4b7a34-8d65-4cc3-8ab0-3477f8a967a6",
    "detectedMapping": {
      "companyName": "company_name",
      "websiteUrl": "website_url",
      "linkedinUrl": "linkedin_url"
    }
  },
  "meta": {
    "endpoint": "csv.enrichment",
    "creditsUsed": 1,
    "creditsRemaining": 999
  }
}
For small lists, use synchronous mode:
curl -X POST "https://www.trysignalbase.com/api/v2/csv-enrichment" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "wait": true,
    "timeout": 30,
    "companies": [
      { "company_name": "Mollie", "website_url": "mollie.com" }
    ]
  }'
If the job completes within the timeout, the response includes status, progress, summary, and results inline. If it is still pending or running, the response remains job-ID based and you should poll the GET endpoint.

Retrieve Results

Polling is free and returns creditsUsed: 0.
curl "https://www.trysignalbase.com/api/v2/csv-enrichment/7f4b7a34-8d65-4cc3-8ab0-3477f8a967a6?limit=50" \
  -H "Authorization: Bearer YOUR_API_KEY"
The response uses strict status values: pending, running, completed, or failed.
{
  "success": true,
  "data": {
    "jobId": "7f4b7a34-8d65-4cc3-8ab0-3477f8a967a6",
    "status": "completed",
    "progress": { "processed": 148, "total": 148 },
    "submittedAt": "2026-05-12T07:25:42.000Z",
    "completedAt": "2026-05-12T07:27:01.000Z",
    "summary": {
      "totalInputs": 148,
      "matched": 87,
      "unmatched": 61,
      "withFundingSignals": 12,
      "withAcquisitionSignals": 3,
      "withHiringSignals": 54,
      "withJobChangeSignals": 0
    },
    "results": [],
    "nextCursor": null
  },
  "meta": {
    "endpoint": "csv.enrichment.get",
    "creditsUsed": 0
  }
}
results is paginated. Use limit up to 100; when nextCursor is not null, request the next page with ?cursor=<nextCursor>&limit=50.

Service Level

  • Processing-time target: Approximately 30 seconds for 100 companies and approximately 2 minutes for 1,000 companies, depending on match complexity and upstream availability.
  • Recommended polling cadence: Poll every 5 seconds for the first 60 seconds, then every 30 seconds. Stop polling after 10 minutes and surface the jobId.
  • Result retention: Job IDs are retrievable for 30 days. After that, the API returns 410 Gone with code job_expired.
  • Maximum Companies: Up to 1,000 companies per request
  • Credit Cost: 1 API credit per accepted submit request; polling costs 0 credits

Rate Limits

TierRequests/minuteConcurrent enrichment jobsMax companies/jobJobs/day
FreeAPI access disabled000
GTM Signals6031,00010
Workflows6031,00010
Signal EngineCustomCustom1,000 by defaultCustom
Team-specific limits may be higher when configured contractually.

Match Rules

Identifier precedence is:
  1. linkedin_url / linkedinUrl / linkedin / company_linkedin_url
  2. website_url / websiteUrl / website / domain
  3. company_name / companyName / name
LinkedIn and website/domain matching require a normalized exact match. If one of those stronger identifiers is provided and no confident match is found, the matcher does not fall back to a fuzzy company-name guess. Company-name matching is used when no LinkedIn or website/domain identifier is provided.

URL & domain normalization

Website and domain values are normalized before matching, so equivalent forms are treated identically — you do not need to pre-clean them:
  • The scheme is optional: https://acme.com, http://acme.com, and acme.com are equivalent.
  • A leading www. is stripped: www.acme.com and acme.com match the same company.
  • A full URL with a path (https://acme.com/about) is reduced to its host (acme.com) for matching.
Provide a website as a full URL or a bare domain via any of website_url, websiteUrl, website, or domain — they are interchangeable. LinkedIn company URLs may be supplied via linkedin_url, linkedinUrl, linkedin, or company_linkedin_url.

Error Handling

The API returns standard HTTP status codes:
  • 200: Job created successfully
  • 400: Invalid request body or missing company identifiers
  • 401: Unauthorized - Invalid or missing API key
  • 402: Insufficient credits
  • 403: Subscription expired
  • 429: Rate limit exceeded
  • 500: Internal server error
Error responses include:
{
  "success": false,
  "error": "Error message description",
  "code": "invalid_company_payload"
}
Known error codes:
CodeHTTP statusMeaning
invalid_company_payload400The request JSON, company list, cursor, or identifiers are invalid.
invalid_api_key401The Authorization header is missing or the API key is invalid.
insufficient_credits402The team does not have enough API credits to create a job.
subscription_expired403The API key belongs to a team without an active subscription.
rate_limited429The team exceeded the endpoint rate limit.
job_not_found404The job ID does not exist for the authenticated team.
job_expired410The job is older than the 30-day retention window.
match_engine_unavailable500The enrichment worker or match engine failed unexpectedly.
When a job itself fails, GET returns HTTP 200 with data.status: "failed" and an error object:
{
  "success": true,
  "data": {
    "jobId": "7f4b7a34-8d65-4cc3-8ab0-3477f8a967a6",
    "status": "failed",
    "error": {
      "code": "match_engine_unavailable",
      "message": "CSV enrichment job failed."
    }
  },
  "meta": {
    "endpoint": "csv.enrichment.get",
    "creditsUsed": 0
  }
}