Fincheck

Batch Import

Upload many leads at once, then follow processing by polling or webhook.

Batch import is the Direct integration for many leads at once. You upload a file or a JSON list, FincheckEngine queues it straight away, and each row is processed in the background exactly like a single lead.

See POST /api/v2/lead/batch in the API Reference →

Before you begin

  • Each row uses the same fields and rules as Sending a Lead.
  • A batch can hold up to 2,000 rows by default. Contact support if you need a different limit.
  • You choose one intent for the whole batch.

1. Prepare the CSV

The first row holds the field names. Each following row is one applicant:

CSV
first_name,last_name,cell_phone_number,email,id_number,popi,gross_income,net_income,loan_amount_required
Thabo,Molefe,0821234567,thabo.molefe@example.com,8001015009087,true,25000,18000,5000
Lerato,Dlamini,0839876543,lerato.dlamini@example.com,9001014800089,true,32000,24000,8000

Use commas or semicolons as separators. XLSX and XLS files are also accepted, but CSV is the most portable. The sample at the bottom of this page has every supported heading.

2. Upload the file

cURL
curl -X POST "https://your-api-origin/api/v2/lead/batch" \
  -H "Authorization: Bearer fce_your_key" \
  -H "Accept: application/json" \
  -F "leads=@lead-batch.csv;type=text/csv" \
  -F "intent=Personal Loans"

Let your HTTP client set the multipart boundary. Do not set Content-Type: multipart/form-data yourself.

Form fieldRequiredUse
leadsRequiredThe CSV, XLSX, or XLS file.
intent or intent_idRequiredThe intent for every row: its title or id from GET /intent.
mapOptionalA JSON object that renames your headings, for example {"mobile":"cell_phone_number"}.
result_urlOptionalAn absolute HTTP or HTTPS URL that receives the final status. See Completion webhook.
partner_idsOptionalPartner ids for rows that do not have their own, as comma-separated ids or a JSON array string.

3. Store the batch id

An accepted upload returns HTTP 202:

JSON
{
  "batch_id": 1842,
  "status": "queued",
  "total_rows": 2
}

4. Check the status

Poll with the same key that uploaded the batch:

cURL
curl "https://your-api-origin/api/v2/lead/batch/1842" \
  -H "Authorization: Bearer fce_your_key" \
  -H "Accept: application/json"
JSON
{
  "batch_id": 1842,
  "status": "completed",
  "accepted": 1,
  "rejected": 1,
  "duplicate": 0,
  "error_count": 0,
  "processed": 2,
  "total_rows": 2,
  "webhook_status": "skipped",
  "results": [
    { "row": 0, "status": "created", "id": "k3mN9pQx", "lead_state": "dispatched" },
    { "row": 1, "status": "rejected", "errors": { "id_number": "must be a valid RSA ID number" } }
  ]
}

Poll every 30 seconds or so, and stop when status is completed or failed.

Batch states

StatusWhat it means
queuedAccepted and waiting to start.
processingRows are being processed. processed counts up towards total_rows.
completedEvery row has a result.
failedThe batch could not be processed. Keep the batch_id and contact support.

Row results

StatusWhat it meansWhat to do
pendingNot processed yet.Nothing.
createdA new lead was created. id is the lead id and lead_state is its current state.Store id.
duplicateThe applicant matched an existing lead. id is the existing lead's id.Store id. Do not resend.
rejectedA field failed validation. errors names each field.Correct the row and send it in a new batch.
errorThe row could not be processed. error describes why.Send the row again later, or contact support.

row is the zero-based position of the data row, so the first row after the headings is 0. results lists the first 500 rows. The counters always cover the whole batch.

Completion webhook

Add result_url to receive the final status instead of polling:

cURL
-F "result_url=https://your-server.example.com/webhooks/fincheck/batches"

When the batch finishes, FincheckEngine sends a POST with a JSON body identical to the status response above.

  • Respond with any 2xx status within 10 seconds. Do the processing after you respond.
  • A failed delivery is retried twice in quick succession. After that, webhook_status is failed.
  • The request is not signed. Treat it as a signal, and confirm the result by calling GET /lead/batch/{id}.

webhook_status is pending, sent, failed, or skipped (no result_url). Polling always works, with or without a webhook.

JSON batches

You can send the batch as JSON instead of a file:

JSON
{
  "intent": "Personal Loans",
  "result_url": "https://your-server.example.com/webhooks/fincheck/batches",
  "leads": [
    {
      "first_name": "Thabo",
      "last_name": "Molefe",
      "cell_phone_number": "0821234567",
      "id_number": "8001015009087",
      "popi": true
    }
  ]
}

A batch-level partner_ids applies only to rows that do not have their own.

Troubleshooting

StatusCauseWhat to do
400The body or file could not be read, or the batch was empty.Check the file format and headings.
401The key is missing or rejected.See Authentication.
403You are reading a batch another affiliate uploaded.Use the key that uploaded it.
404The batch does not exist in this environment.Check the batch_id and environment.
422A batch-level value is wrong: missing intent, invalid result_url, or too many rows.Correct the value and upload again.

To check on a batch, poll its existing batch_id. Uploading the same file again only produces duplicate rows.

Sample CSV

Start with the supported headings and two fictional applicants. Keep intent or intent_id on the multipart form. The default limit is 2,000 rows.

Download sample CSV