Skip to main content

Bulk operations

LeadX has three distinct bulk mechanisms. Picking the right one matters — they have different limits and different failure behaviour.

You want toUseLimit
Create up to a few hundred records now, and know which ones failedPOST /lead/bulk, POST /contact/bulk500 per request
Update or delete a selection, possibly "everything matching a filter"PUT / DELETE on the collectionnone
Load a spreadsheet of tens of thousands of rowsImportstreamed, resumable

Bulk create

POST /lead/bulk and POST /contact/bulk take a batch and create each item independently and in order.

The body may be a bare array, or an object under any of items, leads, contacts, records:

curl -X POST https://api.leadx.in/api/key/protected/contact/bulk \
-H "apikey: $KEY" -H "Content-Type: application/json" \
-d '{
"items": [
{ "formData": { "name": "Ada Lovelace", "email": "ada@example.com" } },
{ "formData": { "name": "Alan Turing", "email": "alan@example.com" } }
]
}'

Each item takes the same shape as the single-create body, so anything you can POST /contact you can put in the array.

Partial success is the contract

A bad row fails on its own; the rest still land. The response tells you exactly which:

{
"ok": true,
"success": true,
"message": "1 of 2 contact(s) created.",
"data": {
"requested": 2,
"created": 1,
"failed": 1,
"items": [ { "index": 0, "ok": true, "_id": "665f..." } ],
"errors": [
{ "index": 1, "message": "Contact already exists.", "status": 400 }
]
}
}

index is the position in the array you sent, so you can fix and resend just the failures. The HTTP status is 200 even when some rows failed — check failed, not the status code.

:::warning The cap is 500 Over 500 items returns 400. The limit exists because each item costs a duplicate lookup, a write and a workflow event inside one HTTP request. For bigger loads, use the import pipeline. :::

Items are created sequentially on purpose: the create path deduplicates against what is already stored, so two identical rows in one payload would both pass that check if they ran concurrently. Running in order means the second one sees the first.

Bulk update

PUT on the collection path (PUT /lead, PUT /contact, PUT /product-service) applies one set of changes to a selection.

{
"ids": ["665f...", "6660..."],
"updateType": "replace",
"formData": { "stage": "Qualified", "priority": "High" }
}
FieldTypeNotes
idsstring[]Documents to update.
nidsstring[]Documents to exclude — meaningful with selectAll.
selectAllbooleanUpdate everything matching the query-string filter instead of a fixed id list.
formDataobjectFields to set. System fields and custom fields alike.
updateTypereplace | appendappend adds to array-valued custom fields instead of overwriting. Default replace.

Selecting everything that matches a filter

selectAll reads the query string for filters, advancedFilters and searchValue — the same parameters as the list endpoint. So "update every Hot lead" is:

curl -X PUT "https://api.leadx.in/api/key/protected/lead?filters=%7B%22status%22%3A%22Hot%22%7D" \
-H "apikey: $KEY" -H "Content-Type: application/json" \
-d '{ "selectAll": true, "formData": { "priority": "High" } }'

:::danger selectAll with no filter means every record selectAll: true and an empty query string selects the whole company. Always send a filters or advancedFilters query parameter with it, and dry-run the same filter against GET first to see totalCount. :::

Bulk delete

DELETE on the collection path, with the selection in the body:

curl -X DELETE https://api.leadx.in/api/key/protected/lead \
-H "apikey: $KEY" -H "Content-Type: application/json" \
-d '{ "ids": ["665f...", "6660..."] }'

Same three fields as bulk update: ids, nids, selectAll, with the same query-string filter behaviour and the same warning.

Sending neither ids nor selectAll is an error (NoLeadSelected_400 and its per-module equivalents) rather than a silent no-op.

Company scoping is always applied on top of your selection, so a bulk delete can never reach another tenant's records even if you pass their ids.

:::note Deletes on leads and contacts are soft Leads and contacts set isDeleted rather than being removed, and deleted files land in a recycle bin (GET /file/recycle-bin). Most other collections delete outright. :::