--- title: "Create and authenticate a service user" description: "Create a service user, assign account roles and permissions, and authenticate API calls for secure automation.\n" source_url: https://dev.digicert.com/account-manager-api/tutorials/create-and-authenticate-a-service-user.html --- Service users are designed for automation. They persist regardless of employee turnover and enable granular permission control for API integrations. In this tutorial, you will: - Get the account ID to assign the service user. - Identify available roles and permissions for the service user. - Create the service user. - Use the returned API token to authenticate your first API call as that service user. ## Before you begin - Completed (or understand) [How to make your first API call](https://dev.digicert.com/md/get-started/make-your-first-api-call.md). - API token with the **Account Administrator** role and the ability to create service users. - Basic familiarity with REST APIs, JSON, and preferred coding language. - If using `curl`, jq installed. Use `jq --version` to verify. ## Endpoint overview | Path | Method | Description | | --- | --- | --- | | `/account/api/v1/account` | GET | Retrieve a list of accounts you have access to | | `/account/api/v1/role` | GET | Retrieve a list of roles and associated permissions available to assign | | `/account/api/v1/user` | POST | Create a new service user with specified roles and permissions | | `/account/api/v1/user/{user_id}` | GET | Get details about a user | ## Step 1: Get your account ID Service users must be assigned to at least one account. You can find the account ID to assign using the `/account/api/v1/account` endpoint. **Request:** **curl** ```bash curl -X GET "https://demo.one.digicert.com/account/api/v1/account" \ -H "x-api-key: ADMIN_API_TOKEN" | jq '.' ``` **python** ```python import requests # Configuration BASE_URL = "https://demo.one.digicert.com" ADMIN_API_TOKEN = "ADMIN_API_TOKEN" response = requests.get( f"{BASE_URL}/account/api/v1/account", headers={"x-api-key": ADMIN_API_TOKEN} ) print(f"Status Code: {response.status_code}") print(response.json()) ``` **Java** ```java import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class ApiExample { public static void main(String[] args) throws Exception { // Configuration String baseUrl = "https://demo.one.digicert.com"; String adminApiToken = "ADMIN_API_TOKEN"; // Send request HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(baseUrl + "/account/api/v1/account")) .header("x-api-key", adminApiToken) .GET() .build(); HttpResponse response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status Code: " + response.statusCode()); System.out.println(response.body()); } } ``` **C#** ```csharp using System; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { // Configuration string baseUrl = "https://demo.one.digicert.com"; string adminApiToken = "ADMIN_API_TOKEN"; // Send request using var client = new HttpClient(); client.DefaultRequestHeaders.Add("x-api-key", adminApiToken); var response = await client.GetAsync($"{baseUrl}/account/api/v1/account"); string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Status Code: {(int)response.StatusCode}"); Console.WriteLine(responseBody); } } ``` **Successful response (200 OK):** ```json [ { "id": "50580ac7-60e4-4df2-a834-d12c1ab79afb", "name": "Example account 1", "active": true, "service_period": { "from": "2021-05-25", "to": "2022-05-25" }, "friendly_identifier": "5258283", "admins": [ { "id": "833e4906-fc45-4bd3-841e-40506c0e8ca8", "email": "api_service_user_1@example.com" }, { "id": "fa8285c7-5e35-4ea8-8cc4-dc95f7dc3cd6", "email": "api_service_user_2@example.com" }, { "id": "7d78b46a-c635-4bda-8b6d-13802046a963", "name": "John Doe", "email": "account_user_1@example.com" } ], "sign_in_methods": [ { "signInMethod": "standard", "status": "enabled", "mfaStatus": "disabled", "clientAuthCertLoginEnabled": false } ], "locale": "en_US" }, { "id": "be5ffbd2-1a50-4675-912f-2fe015812f87", "name": "Example account 2", "active": true, "service_period": { "from": "2021-05-26", "to": "2022-05-26" }, "friendly_identifier": "7092363", "admins": [], "sign_in_methods": [ { "signInMethod": "standard", "status": "enabled", "mfaStatus": "disabled", "clientAuthCertLoginEnabled": false } ], "locale": "en_US" } ] ``` From the returned list of accounts, choose the account you want to work with and save its `id` value. You will need this in Step 3 when you create the service user. ## Step 2: View available roles and permissions Before creating a service user, you need to understand which roles are available in your account. Roles determine what a user (service user in this case) can see and do via the API. The `/account/api/v1/role` endpoint returns all roles (default and custom) and are organized by manager. **Request:** **curl** ```bash curl -X GET "https://demo.one.digicert.com/account/api/v1/role" \ -H "x-api-key: SERVICE_API_TOKEN" | jq '.' ``` **python** ```python import requests # Configuration BASE_URL = "https://demo.one.digicert.com" SERVICE_API_TOKEN = "SERVICE_API_TOKEN" response = requests.get( f"{BASE_URL}/account/api/v1/role", headers={"x-api-key": SERVICE_API_TOKEN} ) print(f"Status Code: {response.status_code}") print(response.json()) ``` **Java** ```java import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class ApiExample { public static void main(String[] args) throws Exception { // Configuration String baseUrl = "https://demo.one.digicert.com"; String serviceApiToken = "SERVICE_API_TOKEN"; // Send request HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(baseUrl + "/account/api/v1/role")) .header("x-api-key", serviceApiToken) .GET() .build(); HttpResponse response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status Code: " + response.statusCode()); System.out.println(response.body()); } } ``` **C#** ```csharp using System; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { // Configuration string baseUrl = "https://demo.one.digicert.com"; string serviceApiToken = "SERVICE_API_TOKEN"; // Send request using var client = new HttpClient(); client.DefaultRequestHeaders.Add("x-api-key", serviceApiToken); var response = await client.GetAsync($"{baseUrl}/account/api/v1/role"); string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Status Code: {(int)response.StatusCode}"); Console.WriteLine(responseBody); } } ``` **Successful response (200 OK):** ```json { "ca_manager": [ { "name": "CM_PKI_MANAGER", "display_name": "CM PKI MANAGER", "description": "Role with CM view permissions", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "CM_KEY_ESCROW", "display_name": "Key Escrow", "description": "CM Key Escrow", "type": "default", "status": "ACTIVE", "access_scope": "account" } ], "account_manager": [ { "name": "AM_ACCOUNT_ADMIN", "display_name": "AM ACCOUNT ADMIN", "description": "Admin role with view and manage permissions", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "AM_DEFAULT_USER", "display_name": "AM DEFAULT USER", "description": "Default role with view permissions", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "AM_ACCOUNT_USER", "display_name": "AM ACCOUNT USER", "description": "Role with view permissions", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "AM_ACCOUNT_MANAGER", "display_name": "Account manager", "description": "AM Account manager", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "AM_USER_MANAGER", "display_name": "User manager", "description": "AM User manager", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "AM_VIEW_ONLY", "display_name": "View only", "description": "AM View only", "type": "default", "status": "ACTIVE", "access_scope": "account" } ], "secure_software_manager": [ { "name": "SSM_KEYLOCKER_ADMIN", "display_name": "SSM KEYLOCKER ADMIN", "description": "Admin role with view and manage SSM permissions", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "SSM_KEYLOCKER_USER", "display_name": "SSM KEYLOCKER USER", "description": "Admin lite role", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "SSM_LEAD", "display_name": "SSM Lead", "description": "SSM Lead", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "SSM_DEVELOPER", "display_name": "SSM Developer", "description": "SSM Developer", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "SSM_TEAM_LEAD", "display_name": "SSM Team Lead", "description": "SSM Team Lead", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "SSM_SIGNER", "display_name": "SSM Signer", "description": "SSM Signer", "type": "default", "status": "ACTIVE", "access_scope": "account" } ], "enterprise_manager": [ { "name": "EM_EPKI_ACCOUNT_MANAGER", "display_name": "EPKI Account Manager", "description": "EPKI Account Manager", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "EM_EPKI_RECOVERY_MANAGER", "display_name": "EPKI Recovery Manager", "description": "EPKI Recovery Manager", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "EM_EPKI_IMPORT_MANAGER", "display_name": "EPKI Import Manager", "description": "EPKI Import Manager", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "EM_EPKI_USER_&_CERT_MANAGER", "display_name": "EPKI User & cert manager", "description": "EPKI User & cert manager", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "EM_EPKI_CERT_PROFILE_MANAGER", "display_name": "EPKI Cert Profile Manager", "description": "EPKI Cert Profile Manager", "type": "default", "status": "ACTIVE", "access_scope": "account" } ], "device_manager": [ { "name": "IOT_CUSTOM_ROLE", "display_name": "Custom role", "description": "Custom role description.", "type": "custom", "status": "ACTIVE", "access_scope": "account" }, { "name": "IOT_ACCOUNT_MANAGER", "display_name": "IOT Account Manager", "description": "IOT Account Manager", "type": "default", "status": "ACTIVE", "access_scope": "account" } ], "document_signing_manager": [ { "name": "DSM_DOCUMENT_SIGNER", "display_name": "DSM DOCUMENT SIGNER", "description": "Role with signer permissions", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "DSM_CLIENT_ADMIN", "display_name": "DSM Client Admin", "description": "DSM Client Admin", "type": "default", "status": "ACTIVE", "access_scope": "account" }, { "name": "DSM_SIGNER", "display_name": "DSM Signer", "description": "DSM Signer", "type": "default", "status": "ACTIVE", "access_scope": "account" } ] } ``` The response body returns a list of user roles for your account. By default, it returns all roles (both default system roles and custom roles) for your primary account, organized by manager. - `account_manager`: Account manager - `ca_manager`: DigiCert® Private CA - `enterprise_manager`: Trust Lifecycle - `device_trust_manager`: Device Trust - `secure_software_manager`: Software Trust - `document_signing_manager`: Document Trust - `device_manager`: IoT Trust Each role object in the response contains these fields: - `name`: The role identifier used in API requests. - `display_name`: Friendly role name - `description`: What the role allows users to do - `type`: Whether it’s a `default` system role or `custom` role - `status`: Whether the role is `ACTIVE` or `ARCHIVED` When you create a service user in the next step, you’ll specify which `roles` to assign using the role `name`, such as `AM_DEFAULT_USER`. > **Tip** > > You can narrow the response using `application_code` and `account_id` query parameters. > > ```bash > curl -X GET "https://demo.one.digicert.com/account/api/v1/role?application_code=account_manager&account_id=ACCOUNT_ID" \ > -H "x-api-key: SERVICE_API_TOKEN" \ > -H "Content-Type: application/json" > ``` ## Step 3: Create the service user Service users require four fields in the request body: - `friendly_name` to identify the service user. - `email_address` for notifications. - `account_id` for association. - `roles` for permissions and manager access. After gathering those details, make a POST request to the `/account/api/v1/user` endpoint. **Request:** **curl** ```bash curl -X POST "https://demo.one.digicert.com/account/api/v1/user" \ -H "x-api-key: ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "friendly_name": "Service User Friendly Name", "email": "jane@example.com", "description": "Service user description", "roles": [ "AM_ACCOUNT_ADMIN" ], "accounts": [ "ACCOUNTS" ] }' | jq '.' ``` **python** ```python import requests # Configuration BASE_URL = "https://demo.one.digicert.com" ADMIN_API_TOKEN = "ADMIN_API_TOKEN" # Request details FRIENDLY_NAME = "Service User Friendly Name" EMAIL = "jane@example.com" DESCRIPTION = "Service user description" ACCOUNTS = "ACCOUNTS" AM_ACCOUNT_ADMIN = "AM_ACCOUNT_ADMIN" payload = { "friendly_name": FRIENDLY_NAME, "email": EMAIL, "description": DESCRIPTION, "accounts": [ACCOUNTS], "roles": [AM_ACCOUNT_ADMIN], } response = requests.post( f"{BASE_URL}/account/api/v1/user", headers={ "x-api-key": ADMIN_API_TOKEN, "Content-Type": "application/json" }, json=payload ) print(f"Status Code: {response.status_code}") print(response.json()) ``` **Java** ```java import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ArrayNode; public class ApiExample { public static void main(String[] args) throws Exception { // Configuration String baseUrl = "https://demo.one.digicert.com"; String adminApiToken = "ADMIN_API_TOKEN"; // Request details String friendlyName = "Service User Friendly Name"; String email = "jane@example.com"; String description = "Service user description"; // Build payload ObjectMapper mapper = new ObjectMapper(); ObjectNode payload = mapper.createObjectNode(); payload.put("friendly_name", friendlyName); payload.put("email", email); payload.put("description", description); ArrayNode accountsArray = mapper.createArrayNode(); accountsArray.add("ACCOUNTS"); payload.set("accounts", accountsArray); ArrayNode rolesArray = mapper.createArrayNode(); rolesArray.add("AM_ACCOUNT_ADMIN"); payload.set("roles", rolesArray); // Send request HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(baseUrl + "/account/api/v1/user")) .header("x-api-key", adminApiToken) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(payload))) .build(); HttpResponse response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status Code: " + response.statusCode()); System.out.println(response.body()); } } ``` **C#** ```csharp using System; using System.Net.Http; using System.Text; using System.Text.Json.Nodes; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { // Configuration string baseUrl = "https://demo.one.digicert.com"; string adminApiToken = "ADMIN_API_TOKEN"; // Request details string friendlyName = "Service User Friendly Name"; string email = "jane@example.com"; string description = "Service user description"; // Build payload var payload = new JsonObject { ["friendly_name"] = friendlyName, ["email"] = email, ["description"] = description, ["accounts"] = new JsonArray { "ACCOUNTS" }, ["roles"] = new JsonArray { "AM_ACCOUNT_ADMIN" } }; // Send request using var client = new HttpClient(); client.DefaultRequestHeaders.Add("x-api-key", adminApiToken); var content = new StringContent( payload.ToJsonString(), Encoding.UTF8, "application/json" ); var response = await client.PostAsync($"{baseUrl}/account/api/v1/user", content); string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Status Code: {(int)response.StatusCode}"); Console.WriteLine(responseBody); } } ``` **Successful response (200 OK):** ```json { "id": "5e0bd5fe-117f-4049-b686-1548b1ee5e14", "email": "api-notifications@example.com", "status": "ACTIVE", "access_scope": "account", "primary_account_id": "449922b5-aad9-4e5b-9025-2bd0daf3619e", "created_at": "2025-10-15T15:40:20Z", "friendly_name": "API Integration Service User", "description": "Service user for certificate automation", "api_token": { "id": "cdfcf47d-b47f-4919-bd1b-c62935312cea", "user_id": "5e0bd5fe-117f-4049-b686-1548b1ee5e14", "name": "API Integration Service User", "token": "bedda3cd381bdfc8b17e10a0bfe350340cc4502c4ea9f41c3230ca6f8a17e97b7faa180727952e31fa1fe3227b2", "enabled": true }, "accounts": [ { "id": "449922b5-aad9-4e5b-9025-2bd0daf3619e", "name": "Demo Account", "active": true } ], "applications": [ { "id": "68e8e9fa-01cf-468f-9aae-f8b3b915f9c3", "name": "Account Manager", "permissions": ["VIEW_AM_ACCOUNT", "VIEW_AM_USER"] } ] } ``` > **Important** > > The `api_token.token` value is displayed only once during creation. Securely store it immediately. There is no way to retrieve it later. ## Step 4: Make your first authenticated request Test the service user's access by using the `/account/api/v1/user/{user_id}` endpoint. Replace `{user_id}` with the service user ID returned in Step 3. **Request:** **curl** ```bash curl -X GET "https://demo.one.digicert.com/account/api/v1/user/USER_ID" \ -H "x-api-key: SERVICE_API_TOKEN" | jq '.' ``` **python** ```python import requests # Configuration BASE_URL = "https://demo.one.digicert.com" SERVICE_API_TOKEN = "SERVICE_API_TOKEN" USER_ID = "USER_ID" response = requests.get( f"{BASE_URL}/account/api/v1/user/{USER_ID}", headers={"x-api-key": SERVICE_API_TOKEN} ) print(f"Status Code: {response.status_code}") print(response.json()) ``` **Java** ```java import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class ApiExample { public static void main(String[] args) throws Exception { // Configuration String baseUrl = "https://demo.one.digicert.com"; String serviceApiToken = "SERVICE_API_TOKEN"; String userId = "USER_ID"; // Send request HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(baseUrl + "/account/api/v1/user/" + userId)) .header("x-api-key", serviceApiToken) .GET() .build(); HttpResponse response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status Code: " + response.statusCode()); System.out.println(response.body()); } } ``` **C#** ```csharp using System; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { // Configuration string baseUrl = "https://demo.one.digicert.com"; string serviceApiToken = "SERVICE_API_TOKEN"; string userId = "USER_ID"; // Send request using var client = new HttpClient(); client.DefaultRequestHeaders.Add("x-api-key", serviceApiToken); var response = await client.GetAsync($"{baseUrl}/account/api/v1/user/{userId}"); string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Status Code: {(int)response.StatusCode}"); Console.WriteLine(responseBody); } } ``` ## Common errors and solutions **AUTHORIZATION_ERROR** ```json { "errors": [ { "code": "AUTHORIZATION_ERROR", "message": "No authentication data provided" } ] } Make sure you include a valid API token with your request using the `x-api-key` header. ``` **no_access** ```json { "errors": [ { "code": "no_access", "message": "Not enough permissions" } ] } Make sure your API token has appropriate roles and permissions. ``` **invalid_input_field** ``` { "errors": [ { "code": "invalid_input_field", "message": "Wrong input or input format" } ] } Check endpoint specifications for valid field values. Check your request body and validate your JSON. ``` **duplicate_error** ```json { "errors": [ { "code": "duplicate_error", "message": "Nickname [name] already exists. Enter a different nickname." } ] } Use a different value for the specified field. ``` ## What's next? - [Set up service user multi-factor authentication](https://dev.digicert.com/md/account-manager-api/tutorials/set-up-service-user-multi-factor-authentication.md)