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 for the device: an onboarding token, an attestation token, or a device certificate. nRF Cloud verifies tokens before creating devices. Certificates are registered under the device ID provided in the row.

A header row is required, and columns may appear in any order. For each data row, provide a value in exactly one of the following columns: onboardingToken, attestationToken, or certificate. Leave any other credential columns blank. A request may contain at most 1000 data rows.

ColumnRequired?Description
deviceIdYesThe device ID to onboard. A token must attest to this ID; if it attests to a different ID, only that row fails. A certificate is registered under this ID.
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.
certificateConditionalFor nRF9160 devices. The device's X.509 certificate in PEM format. Enclose the multiline value in double quotes and include a newline after -----END CERTIFICATE-----, before the closing quote.

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
idStringThe ID of the bulk operation.
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.

{
"id": "01EZZJVDQJPWT7V4FWNVDHNMM5",
"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.