Register multiple devices
19 minute read
A batch job is ideal when all devices use the same certificate management policy. Instead of sending individual requests, you submit one request that processes all devices at once.
In this tutorial, you will:
- Create a division to scope your devices and policies.
- Retrieve the division’s ID for use in later steps.
- Work with templates and certificate profiles to create a certificate management policy and issue bootstrap certificates to multiple devices
- Create a device group and attach the bootstrap certificate management policy
- Retrieve the device group’s ID for use in registration
- Register multiple devices against the device group
Before you begin
Before you begin, make sure you have:
An API key with the following role:
DEVCTM_SOLUTION_ADMINISTRATORProvides division, policy, device group, and device creation.
ica_id to create a certificate management policy.primary_rzone_id for creating a division. You can retrieve it via the List all rendezvous zones endpoint.
Device Trust Manager includes several default resources that are automatically created during provisioning including device rendezvous zones.account_id. You can retrieve it via the DigiCert® Account Manager List accounts endpoint.Default resources
Device Trust Manager includes several default resources that are automatically created during provisioning. These resources provide a starting point for configuring device management and certificate lifecycle operations.
Issuing CA: You’ll use this when creating a certificate management policy. It serves as the certificate authority that issues and signs device certificatesCertificate templates: You’ll use this when requesting or issuing certificates (in this tutorial, you are requesting a bootstrap certificate). It defines the certificate settings and attributes applied to your devices.Device rendezvous zones: You’ll use this during device onboarding. It provides the location information devices need to connect to Device Trust Manager.
Endpoint overview
| Method | Path | Description |
|---|---|---|
| POST | /devicetrustmanager/api/v4/division | Create a division |
| GET | /devicetrustmanager/api/v4/division | List divisions to retrieve the division ID |
| GET | /devicetrustmanager/certificate-configuration-service/api/v1/certificate-template | Get the certificate template ID |
| POST | /devicetrustmanager/certificate-configuration-service/api/v1/certificate-profile | Create a certificate profile |
| POST | /devicetrustmanager/certificate-configuration-service/api/v2/certificate-policy | Create a certificate management policy to issue a bootstrap certificate |
| POST | /devicetrustmanager/api/v4/device-group | Create a device group with the bootstrap policy attached |
| GET | /devicetrustmanager/api/v4/device-group | List device groups to retrieve the device group ID |
| GET | /devicetrustmanager/api/v4/device-group | Get the device group ID |
| POST | /devicetrustmanager/api/v4/device/registration | Register the devices |
Reference values
These enum-typed fields appear across the request bodies in Steps 3 and 4. Use this table as a quick lookup when constructing requests programmatically.
| Field | Used in | Allowed values |
|---|---|---|
certificate_management_methods | Create a certificate management policy to issue a bootstrap certificate | SINGLE, BATCH, TRUST_EDGE, EST, SCEP, CMP_V2, ACME |
key_generation_option | Create a certificate management policy to issue a bootstrap certificate | client_side, server_side, client_or_server_side |
key_generation_type | Create a certificate management policy to issue a bootstrap certificate | RSA_2048, RSA_3072, RSA_4096, P_256, P_384, P_512, ED_25519 |
certificate-template | Get the certificate template ID | end_entity, intermediate |
certificate-profile | Create a certificate profile | csr, certificate_value, unique_certificate_value, signature_algorithm, allow_any_key_type, allowed_key_types, subject.common_name |
Step 1: Create a division
A division is an isolated container for your devices, policies, and device groups. Most production deployments organize divisions by business unit, product line, or customer tenant. Create one before any device-related resources so every resource you create afterward belongs to a known scope.
Request:
curl --request POST \
--url https://demo.one.digicert.com/devicetrustmanager/api/v4/division \
--header 'x-api-key: DEVCTM_SOLUTION_ADMINISTRATOR_API_KEY' \
--data '{
"account_id": "ACCOUNT_ID",
"name": "Example division name",
"description": "Example division description",
"primary_rzone_id": "PRIMARY_RZONE_ID",
"user_ids": []
}'
Set the body fields:
account_id: Your DigiCert ONE account ID (a valid UUID)name: Unique division name (must start and end with an alphanumeric character)description: Free-form description shown in the UI and audit logsprimary_rzone_id: A rendezvous zone configured in Device Trust Manager. This rendezvous zone ID will broker device communication for devices in this division
Successful response (200 OK):
{
"success": {
"code": "DIVISION_CREATED_200",
"verbose": "Example division name created successfully"
}
}
This response carries only a success message—the new division’s id is not returned. Retrieve it via a list query in Get the division ID before continuing.
Step 2: Get the division ID
The create a division endpoint returns a success message, but does not return the new division’s ID. To get the newly created division ID, list the divisions using your account_id and the division name you created in Create a division. Use the returned ID as the division_id for creating a certificate management policy as well as for creating a device group.
Request:
curl -X GET "https://demo.one.digicert.com/devicetrustmanager/api/v4/division?account_id=ACCOUNT_ID&name=Example%20division%20name" \
-H "x-api-key: DEVCTM_SOLUTION_ADMINISTRATOR_API_KEY" \
-H "Content-Type: application/json" | jq '.'
Set the query parameters:
account_id: Your DigiCert ONE account ID. Required to scope the search.name: Exact match on the division name where you created a division. Without this filter, the endpoint returns every division associated with your account.
Successful response (200 OK):
{
"limit": 10,
"offset": 0,
"pagination": true,
"next": false,
"total": 1,
"records": [
{
"created_on": "2026-08-31T09:49:18Z",
"updated_on": "2026-08-31T09:49:18Z",
"name": "Example division name",
"description": "Example division description",
"id": "DIVISION_ID",
"account": {
"id": "ACCOUNT_ID",
"name": "ACCOUNT_NAME"
},
"status": "ACTIVE",
"is_migrated": false
}
]
}
Save the records[0].id value as division_id. You will use it when creating a certificate management policy and when attaching a bootstrap policy to the device group to scope the certificate policy and device group to the division.
Step 3: Create a certificate management policy to issue a bootstrap certificate
Creating a certificate management policy involves adding a Certificate template, creating a Certificate profile, and proceeding to create a Certificate management policy.
For this tutorial, you are going to:
- Select an existing
certificate template(custom certificate template available in your account) - Create a
certificate profile - Create a
certificate management policy
Step 3a: Get the certificate template ID
Certificate templates define the certificate fields and constraints available when you create a certificate profile. Templates are provided as part of your onboarding.
List the templates available to your account and retrieve the ID of the template you want to use for the devices’ certificate management policy.
type=custom to ensure that only eligible templates are returned.Request:
curl -X GET "https://demo.one.digicert.com/devicetrustmanager/certificate-configuration-service/api/v1/certificate-template?account_id=ACCOUNT_ID&type=custom&name=CERTIFICATE_TEMPLATE_NAME&status=ACTIVE&format=x509" \
-H "x-api-key: DEVCTM_SOLUTION_ADMINISTRATOR_API_KEY" \
-H "Content-Type: application/json" | jq '.'
Set the query parameters:
account_id: Your DigiCert ONE account IDtype: Use custom to return only customer-created templates that can be used to create certificate profilesname: URL-encoded name of the certificate template provided during onboardingstatus: UseACTIVEto exclude disabled and deleted templatesformat: Usex509for the bootstrap certificate workflow in this tutorial
Successful response (200 OK):
{
"limit": 20,
"offset": 0,
"pagination": true,
"next": false,
"total": 1,
"records": [
{
"id": "CERTIFICATE_TEMPLATE_ID",
"name": "CERTIFICATE_TEMPLATE_NAME",
"status": "ACTIVE",
"type": "custom",
"format": "x509",
"certificate_type": "end_entity"
}
]
}
Confirm that the selected template is ACTIVE and that its type is custom. Save its id value as CERTIFICATE_TEMPLATE_ID. You will use it while creating a certificate profile.
Step 3b: Create a certificate profile
A certificate profile configures the certificate fields that Device Trust Manager uses when issuing bootstrap certificates. Create the certificate profile from the certificate template you selected in Get the certificate template ID and assign it to the division you created in Create a division.
This tutorial enables a CSR and allows the common name to come from either the CSR or the batch registration data.
Request:
curl --request POST \
--url https://demo.one.digicert.com/devicetrustmanager/certificate-configuration-service/api/v1/certificate-profile \
--header 'x-api-key: DEVCTM_SOLUTION_ADMINISTRATOR_API_KEY' \
--data '{
"account_id": "ID of the account the certificate profile belongs to (UUID)",
"name": "Example batch bootstrap certificate profile",
"ca_connector_type": "digicert_one",
"certificate_template_id": "ID of the certificate template to use in the certificate profile",
"divisions": [
"DIVISION_ID"
],
"omit_primitive_encoding": false,
"body": [
{
"key": "signature_algorithm",
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"value": "match_issuer"
},
{
"key": "subject.common_name",
"optional": true,
"enabled": true,
"sources": [
"user_supplied",
"csr"
],
"value": ""
},
{
"key": "subject.organization_name",
"optional": true,
"enabled": false,
"sources": [],
"value": ""
},
{
"key": "subject.organization_unit",
"optional": true,
"enabled": false,
"sources": [],
"value": []
},
{
"key": "subject.street_address",
"optional": true,
"enabled": false,
"sources": [],
"value": []
},
{
"key": "subject.postal_code",
"optional": true,
"enabled": false,
"sources": [],
"value": ""
},
{
"key": "subject.locality",
"optional": true,
"enabled": false,
"sources": [],
"value": ""
},
{
"key": "subject.state",
"optional": true,
"enabled": false,
"sources": [],
"value": ""
},
{
"key": "subject.country",
"optional": true,
"enabled": false,
"sources": [],
"value": ""
},
{
"key": "subject.email",
"optional": true,
"enabled": false,
"sources": [],
"value": ""
},
{
"key": "key_usage.critical",
"optional": true,
"enabled": true,
"sources": [
"fixed_value"
],
"value": "yes"
},
{
"key": "key_usage.dilithium_additional_values",
"optional": true,
"enabled": false,
"sources": [
"user_supplied",
"csr"
],
"value": []
},
{
"key": "key_usage.sphincs_additional_values",
"optional": true,
"enabled": false,
"sources": [
"user_supplied",
"csr"
],
"value": []
},
{
"key": "extended_key_usage.critical",
"optional": true,
"enabled": true,
"sources": [
"fixed_value"
],
"value": "yes"
},
{
"key": "csr",
"optional": false,
"enabled": true,
"sources": [
"user_supplied"
],
"value": null
},
{
"key": "certificate_value",
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"value": "auto"
},
{
"key": "unique_certificate_value",
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"value": "no"
},
{
"key": "validity.duration_unit",
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"value": "years"
},
{
"key": "validity.duration_value",
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"value": 10
},
{
"key": "allow_any_key_type",
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"value": "yes"
},
{
"key": "allowed_key_types",
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"value": [
"rsa_1024",
"rsa_2048",
"rsa_3072",
"rsa_4096",
"p_256",
"p_384",
"p_521",
"ed_25519",
"MLDSA-44",
"MLDSA-65",
"MLDSA-87",
"SLHDSA-SHAKE-128f",
"SLHDSA-SHA2-128s",
"SLHDSA-SHAKE-128s",
"SLHDSA-SHA2-128f",
"SLHDSA-SHAKE-192s",
"SLHDSA-SHA2-192f",
"SLHDSA-SHA2-192s",
"SLHDSA-SHAKE-192f",
"SLHDSA-SHAKE-256f",
"SLHDSA-SHA2-256s",
"SLHDSA-SHAKE-256s",
"SLHDSA-SHA2-256f"
]
},
{
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"key": "renewal_settings.renew_valid_cert",
"value": "anytime"
},
{
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"key": "renewal_settings.renew_expired_cert",
"value": "anytime"
},
{
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"key": "renewal_settings.renewal_key_pair",
"value": "optional"
},
{
"optional": false,
"enabled": true,
"sources": [
"fixed_value"
],
"key": "renewal_settings.renew_revoked_cert",
"value": true
}
],
"certificate_type": "end_entity"
}'
Set the body fields:
name: Unique certificate profile nameaccount_id: Account that owns the profilecertificate_template_id: Template ID Get the certificate template IDbody: Certificate field configuration. Every entry requireskey,optional,enabled,sources, andvaluedivisions: Division IDs where the profile is available. UseDIVISION_IDfrom Get the division ID
Successful response (201 Created):
{
"id": "CERTIFICATE_PROFILE_ACCOUNT_ID",
"name": "Example certificate profile name",
"account_id": "ACCOUNT_ID",
"certificate_template": {
"id": "CERTIFICATE_TEMPLATE_ID>",
"name": "CERTIFICATE_TEMPLATE_NAME"
},
"allow_bare_public_key": false,
"created_at": "2026-09-03T06:40:04Z",
"status": "ACTIVE",
"body": [
{
"key": "signature_algorithm",
"optional": false,
"sources": [
"fixed_value"
],
"value": "match_issuer",
"enabled": true
},
{
"key": "subject.common_name",
"optional": true,
"sources": [
"user_supplied",
"csr"
],
"enabled": true
},
{
"key": "subject.organization_name",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "subject.organization_unit",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "subject.street_address",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "subject.postal_code",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "subject.locality",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "subject.state",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "subject.country",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "subject.email",
"optional": true,
"sources": [],
"enabled": false
},
{
"key": "key_usage.critical",
"optional": true,
"sources": [
"fixed_value"
],
"value": "yes",
"enabled": true
},
{
"key": "key_usage.dilithium_additional_values",
"optional": true,
"sources": [
"user_supplied",
"csr"
],
"enabled": false
},
{
"key": "key_usage.sphincs_additional_values",
"optional": true,
"sources": [
"user_supplied",
"csr"
],
"enabled": false
},
{
"key": "extended_key_usage.critical",
"optional": true,
"sources": [
"fixed_value"
],
"value": "yes",
"enabled": true
},
{
"key": "certificate_value",
"optional": false,
"sources": [
"fixed_value"
],
"value": "auto",
"enabled": true
},
{
"key": "unique_certificate_value",
"optional": false,
"sources": [
"fixed_value"
],
"value": "no",
"enabled": true
},
{
"key": "validity.duration_unit",
"optional": false,
"sources": [
"fixed_value"
],
"value": "years",
"enabled": true
},
{
"key": "validity.duration_value",
"optional": false,
"sources": [
"fixed_value"
],
"value": 10,
"enabled": true
},
{
"key": "allow_any_key_type",
"optional": false,
"sources": [
"fixed_value"
],
"value": "yes",
"enabled": true
},
{
"key": "allowed_key_types",
"optional": false,
"sources": [
"fixed_value"
],
"value": [
"rsa_1024",
"rsa_2048",
"rsa_3072",
"rsa_4096",
"p_256",
"p_384",
"p_521",
"ed_25519",
"MLDSA-44",
"MLDSA-65",
"MLDSA-87",
"SLHDSA-SHAKE-128f",
"SLHDSA-SHA2-128s",
"SLHDSA-SHAKE-128s",
"SLHDSA-SHA2-128f",
"SLHDSA-SHAKE-192s",
"SLHDSA-SHA2-192f",
"SLHDSA-SHA2-192s",
"SLHDSA-SHAKE-192f",
"SLHDSA-SHAKE-256f",
"SLHDSA-SHA2-256s",
"SLHDSA-SHAKE-256s",
"SLHDSA-SHA2-256f"
],
"enabled": true
},
{
"key": "renewal_settings.renew_valid_cert",
"optional": false,
"sources": [
"fixed_value"
],
"value": "anytime",
"enabled": true
},
{
"key": "renewal_settings.renew_expired_cert",
"optional": false,
"sources": [
"fixed_value"
],
"value": "anytime",
"enabled": true
},
{
"key": "renewal_settings.renewal_key_pair",
"optional": false,
"sources": [
"fixed_value"
],
"value": "optional",
"enabled": true
},
{
"key": "renewal_settings.renew_revoked_cert",
"optional": false,
"sources": [
"fixed_value"
],
"value": true,
"enabled": true
}
],
"enrollment_methods": [],
"certificate_format": "x509",
"certificate_type": "end_entity",
"ca_connector_type": "digicert_one",
"omit_primitive_encoding": false,
"divisions": [
{
"id": "DIVISION_ID",
"name": "Example division name"
}
],
"is_migrated": false,
"editable": true,
"non_limited_by_division_allowed": true,
"server_side_key_generation_allowed": true
}
Step 3c: Create a certificate management policy
A certificate management policy defines how certificates are issued, renewed, and revoked for devices. It outlines the protocols for certificate requests with the use of certificate templates, certificate profiles, and issuing CAs.
Request:
curl --request POST \
--url https://demo.one.digicert.com/devicetrustmanager/certificate-configuration-service/api/v2/certificate-policy \
--header 'x-api-key: DEVCTM_SOLUTION_ADMINISTRATOR_API_KEY' \
--data '{
"certificate_policy": {
"certificate_management_methods": [
"BATCH"
],
"batch_request_parameters": {
"encryption_certificate_source": "provided",
"output_format": "zip",
"certificate_format": "pem",
"report_format": "csv",
"include_chain_option": "include_ica_and_root",
"allow_external_download": false,
"rsa_private_key_syntax": "PKCS8",
"ecdsa_private_key_syntax": "PKCS8",
"passcode_generation_option": "NONE"
},
"name": "Example bootstrap policy",
"ica_id": "ICA_ID",
"created_at": "2026-09-02T07:58:17.495Z",
"certificate_profile_id": "CERT_PROFILE_ID",
"division_id": "DIVISION_ID",
"require_approval_for_enroll": false,
"key_generation_option": "server_side",
"key_generation_type": "rsa_2048",
"allowed_ip_addresses": [],
"labels": []
}
}'
Set the body fields:
certificate_management_methods: Array of certificate issuance methods. Allowed values:SINGLE,BATCH,TRUST_EDGE,EST,SCEP,CMP_V2,ACME. UseBATCHfor registering multiple devices.encryption_certificate_source: How the server obtains the encryption certificate that wraps any returned private key.include_chain_option: Controls how much of the issuance chain accompanies the certificate. Useinclude_ica_and_rootto return the ICA and root alongside the leaf.name: Friendly certificate policy name.ica_id: ID of the issuing CA from DigiCert Private CA that will sign certificates for this policydivision_id: Thedivision_idfrom Get the division IDcertificate_profile_id: Certificate profile ID from DigiCert Private CA that shapes the issued certificatekey_generation_option: One ofclient_side,server_side, orclient_or_server_side. Useclient_or_server_sideto allow either client-supplied keys or server-side generationkey_generation_type: Default key type when the server generates the keypair. One ofRSA_2048,RSA_3072,RSA_4096,P_256,P_384,P_512,ED_25519. Required whenkey_generation_optionisserver_sideorclient_or_server_side
Successful response (201 Created):
{
"certificate_policy": {
"name": "Example bootstrap policy",
"certificate_management_methods": [
"BATCH"
],
"enrollment_methods": [
"BATCH"
],
"allowed_ip_addresses": [],
"key_generation_type": "rsa_2048",
"key_generation_allow_to_change": false,
"key_generation_option": "server_side",
"allow_pre_generated_keys": false,
"ca_connector_type": "digicert_one",
"assign_to_authcert_device": false,
"allow_key_cache": false,
"division_id": "DIVISION_ID",
"require_approval_for_enroll": false,
"require_approval_for_renew": false,
"notification_email_list": [],
"digest_email_notification_period": "do_not_send",
"require_digital_signing": false,
"new_batch_flow": true,
"batch_request_parameters": {
"key_generation_option": "client_side",
"key_generation_allow_to_change": false,
"allow_to_use_pregenerated_keys": false,
"encryption_certificate_source": "provided",
"output_format": "zip",
"certificate_format": "pem",
"rsa_private_key_syntax": "pkcs8",
"ecdsa_private_key_syntax": "pkcs8",
"include_chain_option": "include_ica_and_root",
"report_format": "CSV",
"match_private_key_extension_with_certificate": false,
"allow_external_download": false,
"passcode_generation_option": "none"
},
"migrated_to_new_params": false,
"scep_get_ca_cert_response_with_root": false,
"scep_get_ca_cert_response_der_format": false,
"est_cacerts_include_full_tls_chain": false,
"labels": [],
"is_migrated": false,
"id": "IOT_ID",
"certificate_profile": {
"id": "certificate_profile_ID",
"name": "certificate_profile_name"
},
"created_at": "2026-09-02T09:39:43Z",
"ica": {
"id": "<ICA_ID>",
"name": "Example Intermediate CA name"
},
"status": "ACTIVE",
"allowed_signature_algorithms": [
"sha256WithRSA"
],
"direct_mapping": true,
"account_id": "ACCOUNT_ID",
"certificate_type": "end_entity",
"approvers": [],
"ca_body": "<CA_BODY>",
"ca_chain": [
{
"cert_type": "intermediate",
"blob": "<ICA_BLOB>",
"common_name": "Example_intermediate_CA"
},
{
"cert_type": "root",
"blob": "<ROOT_CA_BLOB>",
"common_name": "Example root CA"
}
],
"certificate_template": {
"id": "CERTIFICATE_TEMPLATE_ID",
"name": "name of the certificate template"
},
"require_approval_for_revoke": false,
"alternative_id": "<ALT_ID>"
}
}
From the response, save the certificate_policy.id value as certificate_policy_id. You will use it while creating a device group, when you attach the policy to the device group, and when you register the devices against the certificate management policy.
Step 4: Create a device group with the bootstrap policy attached
A device group is a logical bucket of devices that share the same policies and assignment rules. Attaching the bootstrap certificate policy to the device group at creation time means every device registered to the group will use that policy automatically. That way registration becomes a single API call rather than a per-device policy assignment.
Request:
curl --location 'https://demo.one.digicert.com/devicetrustmanager/api/v4/device-group' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-api-key: <DEVCTM_SOLUTION_ADMINISTRATOR_API_KEY>' \
--data '{
"name": "Example Device Group",
"description": "Custom description",
"is_static": true,
"account_id": "ACCOUNT_ID",
"division_id": "DIVISION_ID",
"labels": [],
"attributes": [
"device_name"
],
"users": [],
"auth_policy_id": "",
"policies": [
{
"type": "bootstrapCertificate",
"policy_id": "CERTIFICATE_POLICY_ID",
"assignment_name": "Bootstrap policy assignment",
"auth_policy_id": "",
"device_field_mappings": [
{
"key": "device_name",
"field": "csr"
}
],
"time_stamp": 1788344828,
"status": "ACTIVE"
}
],
"desired_attributes": []
}'
Set the body fields:
name: Device group name (must start and end with an alphanumeric character)description: Free-form descriptionis_static: Usetruefor a manually managed group. Set tofalsefor a dynamic group whose membership is driven by attribute-matching rules.account_id: Account ID for device association.division_id: Thedivision_idfrom Step 2attributes: Inventory attribute values that uniquely identify devices in this group. For example,["device_name"]policies: An array describing policies attached to the group. For a bootstrap-only group, include one entry shaped like the example below:{ "type": "bootstrapCertificate", "policy_id": "certificate_policy_id", "assignment_name": "Bootstrap policy assignment", "device_field_mappings": [ { "key": "device_name", "field": "subject.common_name" } ], "status": "ACTIVE" }typemust bebootstrapCertificate(oroperationalCertificatefor an operational policy).device_field_mappingsties an inventory attribute (key) to a certificate subject field (field).Confirm subject field naming convention by queryingGET /devicetrustmanager/certificate-configuration-service/api/v2/certificate-policy/{PolicyID}/enrollment-specificationfor the chosen policy. The exact validfieldvalues are policy-dependent.
Successful response (200 OK):
{
"success": {
"code": "DEVICE_GROUP_CREATED_200",
"verbose": "Device group created"
}
}
Like the create-division endpoint, this response carries only a success message—the new device group’s id is not returned. Retrieve it via a list query using (Get the device group ID) before registering the device.
Step 5: Get the device group ID
The create-device-group endpoint returns only a success message, not the new device group’s id. List device groups filtered by your account_id and the name you chose while creating a device group to retrieve its id, which you will pass as device_group_id while registering the devices.
Request:
curl -X GET "https://demo.one.digicert.com/devicetrustmanager/api/v4/device-group?account_id=ACCOUNT_ID&name=Example%20Device%20Group" \
-H "x-api-key: DEVCTM_SOLUTION_ADMINISTRATOR_API_KEY" \
-H "Content-Type: application/json" | jq '.'
Set the query parameters:
account_idYour DigiCert ONE account ID. Required to scope the search.nameExact match on the device group name from Step 4. Without this filter, the endpoint returns every device group on the account.
Successful response (200 OK):
{
"total": 1,
"limit": 10,
"offset": 0,
"pagination": false,
"next": false,
"records": [
{
"created_on": "2026-05-11T07:14:55Z",
"updated_on": "2026-05-11T07:14:55Z",
"name": "Example Device Group",
"description": "Custom description",
"id": "<DEVICE_GROUP_ID>",
"account_id": "<ACCOUNT_ID>",
"division": {
"id": "<DIVISION_ID>",
"name": "Example division name"
},
"is_static": true,
"attributes": [
"device_name"
],
"labels": [],
"device_attribute_definitions": [],
"status": "ACTIVE"
}
]
}
From the single entry in the records array, save the id value as device_group_id. You will use it while registering the devices to register the device against this group.
Step 6: Register the devices
With the division, certificate policy, and device group in place, you can register the devices. Registration creates the device record, ties it to the group’s bootstrap policy, and triggers issuance of the device’s first certificate using the CSR or public key you provide.
Request:
curl -X GET https://demo.one.digicert.com/devicetrustmanager/certificate-batch-service/api/v1/jobs?job_type=device_registration \
--header 'Accept: application/json' \
--header 'Content-Type: multipart/form-data'
Successful response (200 OK):
{
"limit": 20,
"offset": 0,
"pagination": true,
"next": true,
"total": 633,
"records": [
{
"id": "BATCH_ENROLLMENT_JOB_ID",
"account_id": "ACCOUNT_ID",
"division_id": "DIVISION_ID",
"name": "Example batch job name",
"job_type": "device_registration",
"certificate_policy_id": "CERTIFICATE_POLICY_ID",
"device_group_id": "DEVICE_GROUP_ID",
"metadata": {
"emails": [
"Comma-separated list of email addresses for users who receive a notification email when the batch enrollment job is complete"
],
"passcode_regenerated": false,
"server_side_key_gen": false,
"bootstrap_config_template": "{\"configuration\":{\"device_id\":\"${deviceId}\",\"account_id\":\"ACCOUNT_ID\",\"division_id\":\"DIVISION_ID\",\"device_group_id\":\"DEVICE_GROUP_ID\",\"rendezvous_configuration\":{\"mqtt_endpoint\":{\"primary\":[\"mqtt://MQTT_RENDEZVOUS_ZONE_URL\"]},\"persist_connection\":false}}}",
"client_ip": "IP_ADDRESS",
"rzone_cas": []
},
"status": "failed",
"result": "failure",
"created_at": "2026-09-02T10:55:38Z",
"expire_at": "2026-10-02T10:55:39Z",
"total_items": 14,
"failed_items": 14,
"processing_time": 602,
"retry_count": 0,
"data_available": true,
"error_report_available": false,
"completed_at": "2026-09-02T10:55:39Z"
},
{
"id": "BATCH_ENROLLMENT_JOB_ID",
"account_id": "ACCOUNT_ID",
"division_id": "DIVISION_ID",
"name": "Example batch job name",
"job_type": "device_registration",
"certificate_policy_id": "CERTIFICATE_POLICY_ID",
"device_group_id": "DEVICE_GROUP_ID",
"metadata": {
"emails": [
"Comma-separated list of email addresses for users who receive a notification email when the batch enrollment job is complete"
],
"passcode_regenerated": false,
"server_side_key_gen": true,
"key_type": "rsa_2048",
"encryption_certificate": "The PEM-encoded X.509 certificate used to encrypt sensitive data or payloads with CERTIFICATE_DATA",
"bootstrap_config_template": "{\"configuration\":{\"device_id\":\"${deviceId}\",\"account_id\":\"ACCOUNT_ID\",\"division_id\":\"DIVISION_ID\",\"device_group_id\":\"DEVICE_GROUP_ID\",\"rendezvous_configuration\":{\"mqtt_endpoint\":{\"primary\":[\"mqtt://MQTT_RENDEZVOUS_ZONE_URL\"]},\"persist_connection\":false}}}",
"client_ip": "IP_ADDRESS",
"rzone_cas": []
},
"status": "completed",
"result": "success",
"created_at": "2026-09-01T11:05:34Z",
"expire_at": "2026-10-01T11:05:42Z",
"total_items": 3,
"failed_items": 0,
"processing_time": 7822,
"retry_count": 0,
"data_available": true,
"error_report_available": false,
"completed_at": "2026-09-01T11:05:42Z"
},
{
}
]
}
From the response, save the device’s device_id value. The private_keys[].certificate field carries the issued bootstrap certificate, which the device must install to complete onboarding.
Your device holds the private key for this certificate. The request you sent supplied a CSR carrying the public half of a keypair the device generated locally, so the server only needed to issue and return the certificate. That is the client-side path, and your Step 3 policy supports it alongside server-side generation because you set key_generation_option to client_or_server_side.
If you switch to the server-side path by omitting the csr from the registration request, the response also includes a private_keys[].private_key field. Keep that value secure. It is the device’s identity, and anything holding it can impersonate the device. The policy’s single_cert_request_parameters block from Step 3 controls how the server encrypts the key before returning it; with the TLS session, with the encryption certificate you uploaded, or as a password-protected PKCS12 file. Decrypt it on the receiving system, hand it to the device over a confidential channel, and remove every server-side copy once the device confirms installation.
Common errors and solutions
For general API errors (authentication, rate limits), see Error handling and rate limits.
Invalid name
{
"errors": [
{
"code": "03",
"message": "Name must start with a letter and end with an alphanumeric character. Accepts spaces, special chars (,.;:_-) and simple balanced parentheses."
}
]
}
The name field on division, certificate policy, device group, and device must start with a letter and end with an alphanumeric character. Trailing or leading special characters (-, ., ;, :, _, ,) cause this error. Strip whitespace and review the name format before retrying.
Invalid UUID
{
"errors": [
{
"code": "03",
"message": "Account id should be a valid UUID."
}
]
}
The account_id, division_id, certificate_policy_id, ica_id, certificate_profile_id, and device_group_id fields must be valid UUIDs. This error commonly appears when copying values from a UI that wraps IDs in display formatting. Confirm each ID is a bare UUID with no surrounding quotes, brackets, or whitespace.
Missing required field
{
"errors": [
{
"code": "missing_required_field",
"message": "Name cannot be empty or null or just spaces."
}
]
}
The POST endpoints in this tutorial reject empty or whitespace-only required fields. Audit the request body against the required-field list at the top of each step before retrying.
What’s next?
Now that you have registered multiple devices with a bootstrap certificate, you may want to:
- Register a single device. See Register a single device
- Issue an operational certificate: Create an operational certificate policy and attach it to the device group. Devices authenticate with their long-lived bootstrap credential to request short-lived operational certificates for day-to-day work.
- Add an authentication policy: Configure mutual TLS or passcode-based authentication on the device registration endpoint so devices can re-authenticate without an admin API key.
- Monitor device activity: Wire device events into your monitoring stack. Events such as failed enrollments, certificate issuance, and policy changes are surfaced in Device Trust Manager audit logs.