---
title: "Manage credential lifecycle for document signers"
description: "Cancel, revoke, or reassign credentials as needs change.\n"
source_url: https://dev.digicert.com/content-trust-api/tutorials/manage-credential-lifecycle-for-document-signers.html
---
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 **Content 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
| Method | Path | Description |
|--------|------|-------------|
| GET | /api/v2/credential/{name} | Get credential status |
| PUT | /api/v2/credential/{name}/cancel | Cancel a pending credential |
| PUT | /api/v1/credential/{name}/revoke | Revoke a credential |
| POST | /api/v1/user/{userId}/replace-client-admin | Replace a client administrator |
## Credential status values
A credential progresses through the following statuses during its lifecycle:
| Status | Description |
|--------|-------------|
| `ACTIVE` | Credential is active and available for signing |
| `PENDING_ISSUANCE` | Credential issuance is in progress |
| `DEACTIVATED` | Credential was cancelled before issuance completed |
| `REVOKED` | Credential was revoked after activation |
| `SUSPENDED` | Credential is temporarily suspended |
## Revocation reason codes
Use these reason codes when revoking a credential in Step 3:
| Reason | Description |
|--------|-------------|
| `KEY_COMPROMISE` | Private key was compromised |
| `AFFILIATION_CHANGED` | Signer's organizational affiliation changed |
| `SUPERSEDED` | Credential was replaced by a new one |
| `CESSATION_OF_OPERATION` | Credential 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**
```bash
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 '.'
```
**python**
```python
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())
```
**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 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 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 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):**
```json
{
"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**
```bash
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 '.'
```
**python**
```python
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())
```
**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;
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 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 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):**
```json
{
"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**
```bash
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 '.'
```
**python**
```python
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())
```
**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;
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 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 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):**
```json
{
"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.
> **Important**
>
> This endpoint requires OAuth authentication (`client_id` and `client_secret`), not API key authentication.
**Request:**
**curl**
```bash
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 '.'
```
**python**
```python
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())
```
**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;
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 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 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):**
```json
{
"id": "01234567-89ab-cdef-0123-456789abcdef"
}
```
From the response, save the `id` value. This is the user ID for the new client administrator.