Skip to main content

Create nRF9x Devices in Bulk

POST 

/v1/organizations/:organization_slug/projects/:project_slug/long-range/devices/bulk

Different API host

Send this request to https://api.nrfcloud.com, not the default Memfault API host.

Create multiple Devices for a given Project in one asynchronous request by posting a CSV file.

Each row must contain exactly one credential that attests to the device: an onboarding token or an attestation token. nRF Cloud verifies the credential before creating the device.

A header row is required, and columns may appear in any order. For each data row, provide exactly one of onboardingToken and attestationToken. A request may contain at most 1000 data rows.

ColumnRequired?Description
deviceIdYesThe device ID the row's credential must attest. If the credential attests a different ID, only that row fails.
onboardingTokenConditionalFor nRF93M1 devices. A signed JWT attesting the device and the public key nRF Cloud verifies its JWTs with.
attestationTokenConditionalFor nRF9151 and nRF9161 devices. The attestation token the modem returns from the AT%ATTESTTOKEN command.

Return Value

A 202 Accepted response is returned after the CSV is parsed and request-level validation succeeds. Device creation has not started at that point.

Follow the upload to completion

The response contains a Location header with the URL for tracking the bulk operation. The response body's url field contains the same value.

Follow the URL in the Location header by sending GET requests until status is no longer IN_PROGRESS. Always use the returned URL; its structure is not part of this contract and may change.

The link answers with:

FieldTypeDescription
statusStringIN_PROGRESS, SUCCEEDED, or FAILED. SUCCEEDED means every row onboarded; FAILED means at least one did not.
requestedAtDateTimeWhen the upload was accepted.
completedAtDateTimeWhen every row had been attempted. Absent while status is IN_PROGRESS.
uploadedDataUrlStringURL for downloading the CSV exactly as submitted.
errorSummaryObjectPresent only on FAILED. Carries errorCount and an errors array of { row, deviceId, error }, where row matches the zero-based line number in the uploaded CSV. The header is row 0 and data rows start at 1.

Failure details live in errorSummary, which lists only the rows that failed. Rows absent from it were onboarded, so recovering usually means fixing the listed rows and resubmitting a CSV containing only them.

{
"status": "FAILED",
"requestedAt": "2026-08-19T12:00:00Z",
"completedAt": "2026-08-19T12:00:04Z",
"uploadedDataUrl": "/v1/organizations/acme/projects/demo/bulk-ops-requests/01EZZJVDQJPWT7V4FWNVDHNMM5/uploaded-data",
"errorSummary": {
"errorCount": 1,
"errors": [
{
"row": 1,
"deviceId": "cafe0002-0000-0000-0000-000000000002",
"error": "Can not verify token"
}
]
}
}

Request

Responses

Accepted

Response Headers
    Location

    Link to follow for the result of this upload.