Manage credential lifecycle for document signers

Cancel, revoke, or reassign credentials as needs change.

Credential lifecycle management enables you to monitor, cancel, revoke, and reassign signing credentials through the API. These operations help you maintain control over your organization’s document signing infrastructure.

In this tutorial, you will:

  • Get the status of a credential.
  • Cancel a pending credential.
  • Revoke an active or suspended credential.
  • Replace a client administrator.

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
The signer must have the DSM_DOCUMENT_SIGNER role assigned.
For Step 4 (Replace client administrator): OAuth credentials (client_id and client_secret).
The credential name and user ID for the credential you want to manage.

Endpoint overview

MethodPathDescription
GET/api/v2/credential/{name}Get credential status
PUT/api/v2/credential/{name}/cancelCancel a pending credential
PUT/api/v1/credential/{name}/revokeRevoke a credential
POST/api/v1/user/{userId}/replace-client-adminReplace a client administrator

Credential status values

A credential progresses through the following statuses during its lifecycle:

StatusDescription
ACTIVECredential is active and available for signing
PENDING_ISSUANCECredential issuance is in progress
DEACTIVATEDCredential was cancelled before issuance completed
REVOKEDCredential was revoked after activation
SUSPENDEDCredential is temporarily suspended

Revocation reason codes

Use these reason codes when revoking a credential in Step 3:

ReasonDescription
KEY_COMPROMISEPrivate key was compromised
AFFILIATION_CHANGEDSigner’s organizational affiliation changed
SUPERSEDEDCredential was replaced by a new one
CESSATION_OF_OPERATIONCredential is no longer needed

Step 1: Get credential status

Before you cancel or revoke a credential, retrieve its current status to confirm which operations are available. Only credentials with PENDING_ISSUANCE status can be cancelled, and only ACTIVE or SUSPENDED credentials can be revoked.

Request:

curl -X GET "https://demo.one.digicert.com/documentmanager/api/v2/credential/CREDENTIAL_NAME?user_id=USER_ID" \
  -H "x-api-key: SERVICE_API_TOKEN" | jq '.'
import requests

# Configuration
BASE_URL = "https://demo.one.digicert.com"
SERVICE_API_TOKEN = "SERVICE_API_TOKEN"
CREDENTIAL_NAME = "CREDENTIAL_NAME"
# Query parameters
USER_ID = "USER_ID"
response = requests.get(
    f"{BASE_URL}/documentmanager/api/v2/credential/{CREDENTIAL_NAME}",
    headers={"x-api-key": SERVICE_API_TOKEN},
    params={"user_id": USER_ID}
)

print(f"Status Code: {response.status_code}")
print(response.json())
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 credentialName = "CREDENTIAL_NAME";
        // Query parameters
        String userId = "USER_ID";

        // Send request
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/documentmanager/api/v2/credential/" + credentialName + "?user_id=" + userId))
            .header("x-api-key", serviceApiToken)
            .GET()
            .build();

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

        System.out.println("Status Code: " + response.statusCode());
        System.out.println(response.body());
    }
}
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 credentialName = "CREDENTIAL_NAME";
        // Query parameters
        string userId = "USER_ID";

        // Send request
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("x-api-key", serviceApiToken);
        var response = await client.GetAsync($"{baseUrl}/documentmanager/api/v2/credential/{credentialName}?user_id={userId}");

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

Replace {name} with the credential name. The user_id query parameter is optional.

Successful response (201 OK):

{
  "created_by": "CREATED_BY_VALUE",
  "modified_on": "MODIFIED_ON_VALUE",
  "modified_by": "MODIFIED_BY_VALUE",
  "created_on": "CREATED_ON_VALUE",
  "id": "69f3fea8-a13f-4359-aacd-d03ee3133671",
  "name": "tets4",
  "user_id": "a37322f1-5fd3-40d1-a1bc-a8640466a052",
  "account_id": "d02b6af4-6497-4d12-9b28-ac0678dd3eef",
  "profile_id": "01234567-89ab-cdef-0123-456789abcdef",
  "first_credential": false,
  "status": "ACTIVE",
  "cc_order_id": "01234567-89ab-cdef-0123-456789abcdef"
}

From the response, note the status field. This determines which operations you can perform:

  • If the status is PENDING_ISSUANCE, you can cancel the credential (Step 2).
  • If the status is ACTIVE or SUSPENDED, you can revoke the credential (Step 3).

Step 2: Cancel a credential

Cancel a credential when it is still in PENDING_ISSUANCE status. You might need to cancel a credential if it was created with incorrect organization data or incorrect signer information.

Request:

curl -X PUT "https://demo.one.digicert.com/documentmanager/api/v2/credential/CREDENTIAL_NAME/cancel?user_id=USER_ID" \
  -H "x-api-key: SERVICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "notes": "cancellation notes"
  }' | jq '.'
import requests

# Configuration
BASE_URL = "https://demo.one.digicert.com"
SERVICE_API_TOKEN = "SERVICE_API_TOKEN"
CREDENTIAL_NAME = "CREDENTIAL_NAME"
# Query parameters
USER_ID = "USER_ID"
# Request details
NOTES = "cancellation notes"

payload = {
    "notes": NOTES,
}

response = requests.put(
    f"{BASE_URL}/documentmanager/api/v2/credential/{CREDENTIAL_NAME}/cancel",
    headers={
        "x-api-key": SERVICE_API_TOKEN,
        "Content-Type": "application/json"
    },
    params={"user_id": USER_ID},
    json=payload
)

print(f"Status Code: {response.status_code}")
print(response.json())
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;

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 credentialName = "CREDENTIAL_NAME";
        // Query parameters
        String userId = "USER_ID";
        // Request details
        String notes = "cancellation notes";

        // Build payload
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode payload = mapper.createObjectNode();
        payload.put("notes", notes);

        // Send request
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/documentmanager/api/v2/credential/" + credentialName + "/cancel" + "?user_id=" + userId))
            .header("x-api-key", serviceApiToken)
            .header("Content-Type", "application/json")
            .PUT(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(payload)))
            .build();

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

        System.out.println("Status Code: " + response.statusCode());
        System.out.println(response.body());
    }
}
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 serviceApiToken = "SERVICE_API_TOKEN";
        string credentialName = "CREDENTIAL_NAME";
        // Query parameters
        string userId = "USER_ID";
        // Request details
        string notes = "cancellation notes";

        // Build payload
        var payload = new JsonObject
        {
            ["notes"] = notes
        };

        // Send request
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("x-api-key", serviceApiToken);

        var content = new StringContent(
            payload.ToJsonString(),
            Encoding.UTF8,
            "application/json"
        );

        var response = await client.PutAsync($"{baseUrl}/documentmanager/api/v2/credential/{credentialName}/cancel?user_id={userId}", content);

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

Replace {name} with the credential name. The user_id query parameter is optional.

Successful response (201 OK):

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

The credential status changes to DEACTIVATED. You can verify this by repeating Step 1.

Step 3: Revoke a credential

Revoke a credential that has ACTIVE or SUSPENDED status. Revocation is permanent and cannot be undone.

Request:

curl -X PUT "https://demo.one.digicert.com/documentmanager/api/v1/credential/CREDENTIAL_NAME/revoke?user_id=USER_ID" \
  -H "x-api-key: SERVICE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "REASON"
  }' | jq '.'
import requests

# Configuration
BASE_URL = "https://demo.one.digicert.com"
SERVICE_API_TOKEN = "SERVICE_API_TOKEN"
CREDENTIAL_NAME = "CREDENTIAL_NAME"
# Query parameters
USER_ID = "USER_ID"
# Request details
REASON = "REASON"

payload = {
    "reason": REASON,
}

response = requests.put(
    f"{BASE_URL}/documentmanager/api/v1/credential/{CREDENTIAL_NAME}/revoke",
    headers={
        "x-api-key": SERVICE_API_TOKEN,
        "Content-Type": "application/json"
    },
    params={"user_id": USER_ID},
    json=payload
)

print(f"Status Code: {response.status_code}")
print(response.json())
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;

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 credentialName = "CREDENTIAL_NAME";
        // Query parameters
        String userId = "USER_ID";
        // Request details
        String reason = "REASON";

        // Build payload
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode payload = mapper.createObjectNode();
        payload.put("reason", reason);

        // Send request
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/documentmanager/api/v1/credential/" + credentialName + "/revoke" + "?user_id=" + userId))
            .header("x-api-key", serviceApiToken)
            .header("Content-Type", "application/json")
            .PUT(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(payload)))
            .build();

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

        System.out.println("Status Code: " + response.statusCode());
        System.out.println(response.body());
    }
}
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 serviceApiToken = "SERVICE_API_TOKEN";
        string credentialName = "CREDENTIAL_NAME";
        // Query parameters
        string userId = "USER_ID";
        // Request details
        string reason = "REASON";

        // Build payload
        var payload = new JsonObject
        {
            ["reason"] = reason
        };

        // Send request
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("x-api-key", serviceApiToken);

        var content = new StringContent(
            payload.ToJsonString(),
            Encoding.UTF8,
            "application/json"
        );

        var response = await client.PutAsync($"{baseUrl}/documentmanager/api/v1/credential/{credentialName}/revoke?user_id={userId}", content);

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

Replace {name} with the credential name. The user_id query parameter is required for this endpoint. Set the reason field to one of the revocation reason codes listed above.

Successful response (201 OK):

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

The response confirms the revocation with the updated credential details, including the new status of REVOKED.

Step 4: Replace a client administrator

Replace an existing client administrator with a different user. This operation is useful when an administrator changes roles or leaves the organization.

Request:

curl -X POST "https://demo.one.digicert.com/documentmanager/api/v1/user/USER_ID/replace-client-admin" \
  -H "x-api-key: OAUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john@local.com",
    "first_name": "John",
    "last_name": "Doe",
    "user_name": "abc12345",
    "phone_number": "911234567890",
    "locale": "en_US",
    "description": "abc12345"
  }' | jq '.'
import requests

# Configuration
BASE_URL = "https://demo.one.digicert.com"
OAUTH_TOKEN = "OAUTH_TOKEN"
USER_ID = "USER_ID"
# Request details
EMAIL = "john@local.com"
FIRST_NAME = "John"
LAST_NAME = "Doe"
USER_NAME = "abc12345"
PHONE_NUMBER = "911234567890"
LOCALE = "en_US"
DESCRIPTION = "abc12345"

payload = {
    "email": EMAIL,
    "first_name": FIRST_NAME,
    "last_name": LAST_NAME,
    "user_name": USER_NAME,
    "phone_number": PHONE_NUMBER,
    "locale": LOCALE,
    "description": DESCRIPTION,
}

response = requests.post(
    f"{BASE_URL}/documentmanager/api/v1/user/{USER_ID}/replace-client-admin",
    headers={
        "x-api-key": OAUTH_TOKEN,
        "Content-Type": "application/json"
    },
    json=payload
)

print(f"Status Code: {response.status_code}")
print(response.json())
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;

public class ApiExample {
    public static void main(String[] args) throws Exception {
        // Configuration
        String baseUrl = "https://demo.one.digicert.com";
        String oauthToken = "OAUTH_TOKEN";
        String userId = "USER_ID";
        // Request details
        String email = "john@local.com";
        String firstName = "John";
        String lastName = "Doe";
        String userName = "abc12345";
        String phoneNumber = "911234567890";
        String locale = "en_US";
        String description = "abc12345";

        // Build payload
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode payload = mapper.createObjectNode();
        payload.put("email", email);
        payload.put("first_name", firstName);
        payload.put("last_name", lastName);
        payload.put("user_name", userName);
        payload.put("phone_number", phoneNumber);
        payload.put("locale", locale);
        payload.put("description", description);

        // Send request
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/documentmanager/api/v1/user/" + userId + "/replace-client-admin"))
            .header("x-api-key", oauthToken)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(payload)))
            .build();

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

        System.out.println("Status Code: " + response.statusCode());
        System.out.println(response.body());
    }
}
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 oauthToken = "OAUTH_TOKEN";
        string userId = "USER_ID";
        // Request details
        string email = "john@local.com";
        string firstName = "John";
        string lastName = "Doe";
        string userName = "abc12345";
        string phoneNumber = "911234567890";
        string locale = "en_US";
        string description = "abc12345";

        // Build payload
        var payload = new JsonObject
        {
            ["email"] = email,
            ["first_name"] = firstName,
            ["last_name"] = lastName,
            ["user_name"] = userName,
            ["phone_number"] = phoneNumber,
            ["locale"] = locale,
            ["description"] = description
        };

        // Send request
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("x-api-key", oauthToken);

        var content = new StringContent(
            payload.ToJsonString(),
            Encoding.UTF8,
            "application/json"
        );

        var response = await client.PostAsync($"{baseUrl}/documentmanager/api/v1/user/{userId}/replace-client-admin", content);

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

Replace {userId} with the user ID of the current client administrator you want to replace.

Successful response (201 Created):

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

From the response, save the id value. This is the user ID for the new client administrator.