Bulk create investors (deprecated)
/investors/bulkCreates many investors in one call — the import path for migrations. Each row has the same shape as POST /investors (email, title, first_name, last_name + optional sso_id, external_id, onboarding_uuid and a data_capture map keyed by UDC field reference), with email at most 53 characters. Unlike POST /investors/bulk/create, it has no create-or-return match: a row whose email already belongs to an investor fails with "The email has already been taken." Use POST /investors/bulk/create for create-or-return. A token whose organisation is not the platform organisation gets 422 validation_failed with detail rule platform_organisation, and no row is processed.
Send behaviour mirrors the platform's direct-create: if the organisation has a ClientInvite approval workflow the invite is held; otherwise the invite is sent. Set the request-level auto_send to No to import silently regardless (the common choice for a CRM migration), or Yes to force sending.
Each row needs an onboarding_uuid whenever the organisation has published at least one onboarding journey, exactly as POST /investors does; rows without one are reported as failed rather than imported journeyless.
The batch is best-effort: a row that fails (duplicate email, unknown UDC reference, missing onboarding journey, …) is reported in results with its error and does not abort the rest. Maximum 500 rows per call.
Deprecated: withdrawn on 2027-06-30. POST /investors/bulk/create replaces it, with items, per-item auto_send and a job above 100 items; every answer carries a Link header with rel="successor-version". This route keeps its old body and answer.
Request body
application/json, required
- One of:
Overrides the approval-aware default for every row. Omit to use the default (send unless a ClientInvite approval workflow exists);
Noimports silently.Yes,No
{
"auto_send": "No",
"investors": [
{
"email": "stuart@example.com",
"title": "Mr",
"first_name": "Stuart",
"last_name": "Parkinson",
"external_id": "CRM-ODS-row3",
"data_capture": {
"phone_number": "+44 20 7946 0000"
}
},
{
"email": "adam@example.com",
"title": "Dr",
"first_name": "Adam",
"last_name": "Reynolds"
}
]
}Responses
Per-row result report. created/failed/invites_sent summarise the batch; results lists each row's outcome in request order.
{
"created": 1,
"failed": 1,
"invites_sent": 0,
"results": [
{
"index": 0,
"email": "stuart@example.com",
"status": "created",
"id": "9a1f0028-1111-2222-3333-444455556666",
"invite_sent": false
},
{
"index": 1,
"email": "adam@example.com",
"status": "failed",
"error": "The email has already been taken."
}
]
}Authorization failed. error.code is one of org_disabled,
ip_blocked, missing_scope, scope_disabled, user_disabled.
Request validation failed (HTTP 422). The body is either the Laravel
validation envelope (message + field-keyed errors) or the API error
envelope for domain rejections (e.g. form_type_not_supported,
folder_locked, parent_not_found, folder_not_empty).
Examples
curl -X POST https://your-org-domain/kong/core/api/v2/investors/bulk\
-H "Authorization: Bearer $HELM_API_KEY"\
-H "Content-Type: application/json"\
-d '{
"auto_send": "No",
"investors": [
{
"email": "stuart@example.com",
"title": "Mr",
"first_name": "Stuart",
"last_name": "Parkinson",
"external_id": "CRM-ODS-row3",
"data_capture": {
"phone_number": "+44 20 7946 0000"
}
},
{
"email": "adam@example.com",
"title": "Dr",
"first_name": "Adam",
"last_name": "Reynolds"
}
]
}'