Onboard a signer and issue a signing credential

Create a signer and issue credentials for document signing.

Document Trust Manager enables signers to digitally sign documents using API-managed credentials. These APIs replace the legacy validation-based workflow by letting you create signers directly and issue credentials as needed.

In this tutorial, you will:

  • Create a signer as a Document Trust Manager user.
  • Update the signer’s details.
  • Create a credential for the signer.

Before you begin

Before you begin, make sure you have:

A DigiCert ONE account with Document Trust Manager access.
A service user with API key authentication. For instructions, see Create a service user.

API token with the following permissions:

  • Permission to create and update users
  • Permission to create and manage credentials
  • Permission to access the required DigiCert ONE accounts
Your DigiCert ONE account ID (account_id).
Your organization ID (org_id) for credential creation in Step 3.

Endpoint overview

MethodPathDescription
POST/api/v1/userCreate a signer
PUT/api/v1/user/{userId}Update signer details
POST/api/v2/credentialCreate a credential

Step 1: Create a signer

To onboard a new signer, create them as a Document Trust Manager user. This step replaces the legacy flow where you had to create a validation first. The signer is created directly as a user and assigned the DSM_DOCUMENT_SIGNER role.

Request:

curl -X POST "https://demo.one.digicert.com/documentmanager/api/v1/user" \
  -H "x-api-key: SERVICE_USER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "user_name": "user1710238743839",
  "email": "james.demo.1@example.com",
  "first_name": "James",
  "last_name": "Smith",
  "user_type": "standard",
  "accounts": [
    "f9cd7525-b1ab-4067-96da-b0faac7212f6"
  ],
  "roles": [
    "DSM_DOCUMENT_SIGNER"
  ],
  "is_pipl_accepted": true,
  "is_tou_accepted": true,
  "description": "user created by api",
  "phone_number": 919999988888,
  "locale": "en_US"
}' \
  | jq '.'
import requests

response = requests.post(
    "https://demo.one.digicert.com/documentmanager/api/v1/user",
    headers={"x-api-key": "SERVICE_USER_API_TOKEN", "Content-Type": "application/json"},
    json={
        "user_name": "user1710238743839",
        "email": "james.demo.1@example.com",
        "first_name": "James",
        "last_name": "Smith",
        "user_type": "standard",
        "accounts": [
            "f9cd7525-b1ab-4067-96da-b0faac7212f6"
        ],
        "roles": [
            "DSM_DOCUMENT_SIGNER"
        ],
        "is_pipl_accepted": true,
        "is_tou_accepted": true,
        "description": "user created by api",
        "phone_number": 919999988888,
        "locale": "en_US"
    }
)

print(f"Status: {response.status_code}")
if response.status_code != 204:
    print(response.json())
import java.net.http.*;
import java.net.URI;

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://demo.one.digicert.com/documentmanager/api/v1/user"))
    .header("x-api-key", "SERVICE_USER_API_TOKEN")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"user_name\": \"user1710238743839\", \"email\": \"james.demo.1@example.com\", \"first_name\": \"James\", \"last_name\": \"Smith\", \"user_type\": \"standard\", \"accounts\": [\"f9cd7525-b1ab-4067-96da-b0faac7212f6\"], \"roles\": [\"DSM_DOCUMENT_SIGNER\"], \"is_pipl_accepted\": true, \"is_tou_accepted\": true, \"description\": \"user created by api\", \"phone_number\": 919999988888, \"locale\": \"en_US\"}"))
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

System.out.println("Status: " + response.statusCode());
System.out.println(response.body());
using System.Net.Http;
using System.Text;
using System.Text.Json;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "SERVICE_USER_API_TOKEN");

var content = new StringContent(@"{
  ""user_name"": ""user1710238743839"",
  ""email"": ""james.demo.1@example.com"",
  ""first_name"": ""James"",
  ""last_name"": ""Smith"",
  ""user_type"": ""standard"",
  ""accounts"": [
    ""f9cd7525-b1ab-4067-96da-b0faac7212f6""
  ],
  ""roles"": [
    ""DSM_DOCUMENT_SIGNER""
  ],
  ""is_pipl_accepted"": true,
  ""is_tou_accepted"": true,
  ""description"": ""user created by api"",
  ""phone_number"": 919999988888,
  ""locale"": ""en_US""
}",
    Encoding.UTF8, "application/json");

var response = await client.PostAsync("https://demo.one.digicert.com/documentmanager/api/v1/user", content);

Console.WriteLine($"Status: {(int)response.StatusCode}");
Console.WriteLine(await response.Content.ReadAsStringAsync());

Set user_type to standard. The roles array must include DSM_DOCUMENT_SIGNER.

Request fields

FieldTypeRequiredDescription
user_nameStringYesSigner username
emailStringYesSigner email address
first_nameStringYesFirst name
last_nameStringYesLast name
user_typeStringYesUse standard
descriptionStringNoDescription of the user
phone_numberStringNoContact number
accountsArrayYesDTM account IDs
localeStringNoDefault: en_US
rolesArrayYesMust include DSM_DOCUMENT_SIGNER
is_pipl_acceptedBooleanYesIndicates PIPL acceptance
is_tou_acceptedBooleanYesIndicates TOU acceptance

Successful response (201 Created):

{
  "id": "01234567-89ab-cdef-0123-456789abcdef",
}

From the response, save the id value. This is the signer’s user ID. You need this as the {userId} path parameter in Step 2 and the userId field in Step 3.

Step 2: Update the signer

After creating a signer, you can update their details if any information changes or was entered incorrectly. The account field with nested id is required for every update request.

Request:

curl -X PUT "https://demo.one.digicert.com/documentmanager/api/v1/user/01234567-89ab-cdef-0123-456789abcdef" \
  -H "x-api-key: SERVICE_USER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "account": {
    "id": "account_id",
    "name": "name_value"
  },
  "email": "james.demo.1@example.com",
  "first_name": "James",
  "last_name": "Smith",
  "phone_number": 919999988888,
  "locale": "en_US"
}' \
  | jq '.'
import requests

USER_ID = "01234567-89ab-cdef-0123-456789abcdef"

response = requests.put(
    f"https://demo.one.digicert.com/documentmanager/api/v1/user/{USER_ID}",
    headers={"x-api-key": "SERVICE_USER_API_TOKEN", "Content-Type": "application/json"},
    json={
        "account": {
            "id": "account_id",
            "name": "name_value"
        },
        "email": "james.demo.1@example.com",
        "first_name": "James",
        "last_name": "Smith",
        "phone_number": 919999988888,
        "locale": "en_US"
    }
)

print(f"Status: {response.status_code}")
if response.status_code != 204:
    print(response.json())
import java.net.http.*;
import java.net.URI;

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://demo.one.digicert.com/documentmanager/api/v1/user/01234567-89ab-cdef-0123-456789abcdef"))
    .header("x-api-key", "SERVICE_USER_API_TOKEN")
    .header("Content-Type", "application/json")
    .PUT(HttpRequest.BodyPublishers.ofString("{\"account\": {\"id\": \"account_id\", \"name\": \"name_value\"}, \"email\": \"james.demo.1@example.com\", \"first_name\": \"James\", \"last_name\": \"Smith\", \"phone_number\": 919999988888, \"locale\": \"en_US\"}"))
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

System.out.println("Status: " + response.statusCode());
System.out.println(response.body());
using System.Net.Http;
using System.Text;
using System.Text.Json;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "SERVICE_USER_API_TOKEN");

var content = new StringContent(@"{
  ""account"": {
    ""id"": ""account_id"",
    ""name"": ""name_value""
  },
  ""email"": ""james.demo.1@example.com"",
  ""first_name"": ""James"",
  ""last_name"": ""Smith"",
  ""phone_number"": 919999988888,
  ""locale"": ""en_US""
}",
    Encoding.UTF8, "application/json");

var response = await client.PutAsync("https://demo.one.digicert.com/documentmanager/api/v1/user/01234567-89ab-cdef-0123-456789abcdef", content);

Console.WriteLine($"Status: {(int)response.StatusCode}");
Console.WriteLine(await response.Content.ReadAsStringAsync());

Replace {userId} with the signer’s user ID from Step 1.

Successful response (204 No Content):

A 204 response confirms the update was successful. No response body is returned.

Verify the update by retrieving the user details if needed.

Step 3: Create a credential

Once the signer exists, create a credential to enable document signing. This step also initiates the validation process automatically.

Request:

curl -X POST "https://demo.one.digicert.com/documentmanager/api/v2/credential" \
  -H "x-api-key: SERVICE_USER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "productName": "AATL Electronic Seal | ZertES",
  "countryCode": "IN",
  "organization": {
    "id": "org_id",
    "contacts": []
  },
  "label": "tets3",
  "userId": "user_id"
}' \
  | jq '.'
import requests

response = requests.post(
    "https://demo.one.digicert.com/documentmanager/api/v2/credential",
    headers={"x-api-key": "SERVICE_USER_API_TOKEN", "Content-Type": "application/json"},
    json={
        "productName": "AATL Electronic Seal | ZertES",
        "countryCode": "IN",
        "organization": {
            "id": "org_id",
            "contacts": []
        },
        "label": "tets3",
        "userId": "user_id"
    }
)

print(f"Status: {response.status_code}")
if response.status_code != 204:
    print(response.json())
import java.net.http.*;
import java.net.URI;

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://demo.one.digicert.com/documentmanager/api/v2/credential"))
    .header("x-api-key", "SERVICE_USER_API_TOKEN")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"productName\": \"AATL Electronic Seal | ZertES\", \"countryCode\": \"IN\", \"organization\": {\"id\": \"org_id\", \"contacts\": []}, \"label\": \"tets3\", \"userId\": \"user_id\"}"))
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

System.out.println("Status: " + response.statusCode());
System.out.println(response.body());
using System.Net.Http;
using System.Text;
using System.Text.Json;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "SERVICE_USER_API_TOKEN");

var content = new StringContent(@"{
  ""productName"": ""AATL Electronic Seal | ZertES"",
  ""countryCode"": ""IN"",
  ""organization"": {
    ""id"": ""org_id"",
    ""contacts"": []
  },
  ""label"": ""tets3"",
  ""userId"": ""user_id""
}",
    Encoding.UTF8, "application/json");

var response = await client.PostAsync("https://demo.one.digicert.com/documentmanager/api/v2/credential", content);

Console.WriteLine($"Status: {(int)response.StatusCode}");
Console.WriteLine(await response.Content.ReadAsStringAsync());

Set productName to the signing product for your account. The organization object must include the organization id and a contacts array with at least one contact of type VERIFIED_CONTACT.

Successful response (201 OK):

{
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "status": "active"
}

The response includes credential identifiers, order details, and status. Save the credential name to use with the credential management APIs.