Register multiple devices

Register multiple devices and issue each device a bootstrap certificate through one asynchronous batch job.

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:

A DigiCert® ONE account with Device Trust Manager access.

An API key with the following role:

  • DEVCTM_SOLUTION_ADMINISTRATOR Provides division, policy, device group, and device creation.
An issuing CA (ICA) configured in DigiCert® Private CA. You will need its ica_id to create a certificate management policy.
An existing certificate profile
A rendezvous zone configured in Device Trust Manager. You will need its 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.
Your DigiCert ONE account_id. You can retrieve it via the DigiCert® Account Manager List accounts endpoint.
A certificate signing request (CSR) or bare public key for the device you are registering. You will present this while creating a certificate management policy.

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 certificates
  • Certificate 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

MethodPathDescription
POST/devicetrustmanager/api/v4/divisionCreate a division
GET/devicetrustmanager/api/v4/divisionList divisions to retrieve the division ID
GET/devicetrustmanager/certificate-configuration-service/api/v1/certificate-templateGet the certificate template ID
POST/devicetrustmanager/certificate-configuration-service/api/v1/certificate-profileCreate a certificate profile
POST/devicetrustmanager/certificate-configuration-service/api/v2/certificate-policyCreate a certificate management policy to issue a bootstrap certificate
POST/devicetrustmanager/api/v4/device-groupCreate a device group with the bootstrap policy attached
GET/devicetrustmanager/api/v4/device-groupList device groups to retrieve the device group ID
GET/devicetrustmanager/api/v4/device-groupGet the device group ID
POST/devicetrustmanager/api/v4/device/registrationRegister 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.

FieldUsed inAllowed values
certificate_management_methodsCreate a certificate management policy to issue a bootstrap certificateSINGLE, BATCH, TRUST_EDGE, EST, SCEP, CMP_V2, ACME
key_generation_optionCreate a certificate management policy to issue a bootstrap certificateclient_side, server_side, client_or_server_side
key_generation_typeCreate a certificate management policy to issue a bootstrap certificateRSA_2048, RSA_3072, RSA_4096, P_256, P_384, P_512, ED_25519
certificate-templateGet the certificate template IDend_entity, intermediate
certificate-profileCreate a certificate profilecsr, 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 logs
  • primary_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.

Certificate profiles and policies can be created only from custom (non-system) certificate templates. When listing templates, filter the results using 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 ID
  • type: Use custom to return only customer-created templates that can be used to create certificate profiles
  • name: URL-encoded name of the certificate template provided during onboarding
  • status: Use ACTIVE to exclude disabled and deleted templates
  • format: Use x509 for 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 name
  • account_id: Account that owns the profile
  • certificate_template_id: Template ID Get the certificate template ID
  • body: Certificate field configuration. Every entry requires key, optional, enabled, sources, and value
  • divisions: Division IDs where the profile is available. Use DIVISION_ID from 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. Use BATCH for 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. Use include_ica_and_root to 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 policy
  • division_id: The division_id from Get the division ID
  • certificate_profile_id: Certificate profile ID from DigiCert Private CA that shapes the issued certificate
  • key_generation_option: One of client_side, server_side, or client_or_server_side. Use client_or_server_side to allow either client-supplied keys or server-side generation
  • key_generation_type: Default key type when the server generates the keypair. One of RSA_2048, RSA_3072, RSA_4096, P_256, P_384, P_512, ED_25519. Required when key_generation_option is server_side or client_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 description

  • is_static: Use true for a manually managed group. Set to false for a dynamic group whose membership is driven by attribute-matching rules.

  • account_id: Account ID for device association.

  • division_id: The division_id from Step 2

  • attributes: 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"
    }
    

    type must be bootstrapCertificate (or operationalCertificate for an operational policy). device_field_mappings ties an inventory attribute (key) to a certificate subject field (field).

    Confirm subject field naming convention by querying GET /devicetrustmanager/certificate-configuration-service/api/v2/certificate-policy/{PolicyID}/enrollment-specification for the chosen policy. The exact valid field values 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_id Your DigiCert ONE account ID. Required to scope the search.
  • name Exact 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.