Skip to main content
POST
/
api
/
v1
/
leads
/
import
curl -X POST "https://api.foxreach.io/api/v1/leads/import" \
  -H "X-API-Key: otr_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "restoreSoftDeleted": true,
    "leads": [
      {
        "email": "[email protected]",
        "firstName": "Alex",
        "company": "Acme",
        "tags": ["enterprise", "q1-outreach"],
        "customFields": { "industry": "fintech" }
      },
      {
        "email": "[email protected]",
        "firstName": "Sam",
        "title": "Head of RevOps"
      }
    ]
  }'
{
  "data": {
    "created": 2,
    "restored": 0,
    "duplicates": 0,
    "errors": 0,
    "duplicateEmails": [],
    "errorDetails": []
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.foxreach.io/llms.txt

Use this file to discover all available pages before exploring further.

Use this endpoint instead of looping Create Lead when you have a list of leads to ingest. You get back a single response with counts of created, restored, duplicates, and errors — no per-row 409s, no manual retry logic.

Request Body

leads
array
required
Array of lead objects. Each item supports the same fields as Create Lead — at minimum email, plus any of firstName, lastName, company, title, phone, linkedinUrl, website, notes, source, status, customFields, tags. Maximum 1000 leads per request.
restoreSoftDeleted
boolean
default:"true"
When true (default), leads with the same email as a previously soft-deleted record are restored (their deletedAt is cleared and the existing fields are merged with the request payload). When false, those rows are counted as duplicates instead.

Response

{
  "data": {
    "created":        142,
    "restored":         8,
    "duplicates":      12,
    "errors":           1,
    "duplicateEmails": ["[email protected]", "..."],
    "errorDetails":    [{ "email": "", "reason": "empty email" }]
  }
}
FieldDescription
createdNet-new lead rows inserted.
restoredPreviously soft-deleted rows whose deletedAt was cleared and whose campaign membership counts were re-incremented.
duplicatesRows skipped because an active lead with that email already exists, or because the same email appeared earlier in the request.
errorsRows skipped due to validation issues (empty email, etc.).
duplicateEmailsFirst 100 duplicate emails for debugging.
errorDetailsFirst 100 invalid rows with reasons.
In-request duplicate emails are caught — the first occurrence wins, subsequent rows with the same email are counted as duplicates.
curl -X POST "https://api.foxreach.io/api/v1/leads/import" \
  -H "X-API-Key: otr_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "restoreSoftDeleted": true,
    "leads": [
      {
        "email": "[email protected]",
        "firstName": "Alex",
        "company": "Acme",
        "tags": ["enterprise", "q1-outreach"],
        "customFields": { "industry": "fintech" }
      },
      {
        "email": "[email protected]",
        "firstName": "Sam",
        "title": "Head of RevOps"
      }
    ]
  }'
{
  "data": {
    "created": 2,
    "restored": 0,
    "duplicates": 0,
    "errors": 0,
    "duplicateEmails": [],
    "errorDetails": []
  }
}

Errors

StatusDescription
400More than 1000 leads in leads, or empty array
402Workspace plan contact limit would be exceeded by the request
422Invalid request body (malformed JSON, bad field types)
429Rate limit exceeded — see Rate Limit section below

Rate Limit

  • 100 requests per minute, per API key (the same v1 limit as every other endpoint).
  • A bulk import of 1000 leads counts as 1 request, not 1000. This is the whole point of the endpoint — your effective ingestion rate goes from 100 leads/minute (looping single create) to 100,000 leads/minute (looping this endpoint).
  • Response includes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset headers.
For client-side retry/backoff patterns, see Rate Limiting.

When to use this vs. Create Lead

Use Create Lead when…Use Bulk Import when…
You have a single lead from a form or webhookYou’re ingesting from a CSV, spreadsheet, or external data source
You need the full lead row in the responseYou need a structured dedup report
You’re inserting fewer than ~10 rowsYou have anywhere from 10 to 1000 rows per call
You want a 409 conflict surfaced per rowYou want to keep going past dups and restore soft-deleted