---
title: "Audit API activity for compliance reporting"
description: "Use audit logs API to query account activity, filter events, paginate results, and support compliance reporting.\n"
source_url: https://dev.digicert.com/account-manager-api/tutorials/audit-api-activity-for-compliance-reporting.html
---
Audit logs in DigiCert® Account Manager record actions performed in your account, including user creation, API token generation, and sign-in events. Programmatic access to these logs can support security monitoring, internal investigations, and audit evidence collection for frameworks such as SOC 2, PCI DSS, and internal security policies.
In this tutorial, you will:
- Query recent audit log entries to identify available fields and filter values.
- Filter audit log entries by date range and resource type.
- Paginate through large result sets.
- Resolve full user details for users referenced in audit entries.
- Resolve full account details for accounts referenced in audit entries.
## Before you begin
- A DigiCert ONE account with Account Manager access.
- An API token with one of the following roles:
- `AM_ACCOUNT_ADMIN` - View and manage all account resources, including audit logs.
- `AM_VIEW_ONLY` - View account resources and audit logs.
- `AM_USER_MANAGER` - Manage users and view audit logs.
- Existing activity in your account (users created, API tokens generated, sign-ins) so audit log entries are available to query.
- cURL or an HTTP client installed. Use `curl --version` to verify.
## Endpoint overview
| Method | Path | Description |
|--------|------|-------------|
| GET | `/account/api/v1/audit-log` | List audit log entries |
| GET | `/account/api/v1/user/{user_id}` | Get user details |
| GET | `/account/api/v1/account/{account_id}` | Get account details |
## Audit log query parameters
The audit log endpoint accepts several query parameters for filtering and pagination. You can combine these parameters to narrow results progressively.
| Parameter | Type | Description |
|-----------|------|-------------|
| `user_name` | string | Filter by username (contains match) |
| `action` | string | Filter by action (exact match) |
| `resource_types` | string | Filter by resource type, comma-separated (exact match) |
| `resource_id` | string | Filter by resource ID (exact match) |
| `status` | string | Filter by status (exact match) |
| `account_id` | string | Filter by account ID (exact match) |
| `from` | string | Start date, format: `YYYY-MM-DD` |
| `to` | string | End date, format: `YYYY-MM-DD` |
| `sort` | string | Sort field and direction, format: `field:direction` |
| `offset` | integer | Index of first result to return |
| `limit` | integer | Maximum results to return (default: `20`, capped at 1000) |
### Sort fields
| Field | Description |
|-------|-------------|
| `timestamp` | Date and time of the action |
| `action` | Logged action type |
| `status` | Whether the action succeeded or failed |
| `description` | Friendly description of the action |
Sort direction is `asc` (default) or `desc`. Example: `sort=timestamp:desc`.
### Action values
The `action` query parameter requires an exact match from the following values:
| Value | Description |
|-------|-------------|
| `CREATE` | Resource was created |
| `UPDATE` | Resource was modified |
| `DELETE` | Resource was deleted |
| `LOGIN` | User signed in |
| `LOGOUT` | User signed out |
| `LOGIN_ERROR` | Sign-in attempt failed |
| `UPDATE_PASSWORD` | User changed their password |
| `UPDATE_TOTP` | User updated TOTP multi-factor settings |
| `DISABLED` | Resource was disabled |
| `ENABLED` | Resource was enabled |
| `SEND_RESET_PASSWORD` | Password reset email was sent |
| `TERMS_AND_CONDITIONS` | User accepted terms and conditions |
| `LICENSE_REGISTERED` | License was registered |
| `FEATURE_ENABLED` | Account feature was enabled |
| `FEATURE_DISABLED` | Account feature was disabled |
| `LOW_LICENSE_WARNING_SENT` | Low license warning email was sent |
| `ACCOUNT_EXPIRY_EMAIL_SENT` | Account expiry email was sent |
| `API_ACCESS_TOKEN_EXPIRY_EMAIL_SENT` | API token expiry email was sent |
| `CLIENT_AUTH_CERT_EXPIRY_EMAIL_SENT` | Client auth cert expiry email was sent |
| `SERVICE_USER_EXPIRY_EMAIL_SENT` | Service user expiry email was sent |
| `SAML_IDP_CERT_EXPIRY_EMAIL_SENT` | SAML IdP cert expiry email was sent |
### Resource types
The `resource_types` query parameter requires an exact match. Use a comma-separated list to filter by multiple types.
| Value | Description |
|-------|-------------|
| `ACCOUNT` | Account configuration changes |
| `USER` | Standard user actions |
| `SERVICE_USER` | Service user actions |
| `APIKEY` | API token events |
| `CLIENT_AUTH_CERT` | Client authentication certificate events |
| `SAML2_CONFIG` | SAML 2.0 configuration changes |
| `OIDC_CONFIG` | OpenID Connect configuration changes |
| `SSO_SAML` | SAML single sign-on events |
| `SSO_OIDC` | OpenID Connect single sign-on events |
| `OAUTH_CLIENT` | OAuth client events |
| `OAUTH_CONFIG` | OAuth configuration changes |
| `LICENSE` | License events |
| `ROLE` | Role assignment changes |
| `BASIC_AUTH` | Basic authentication events |
| `DIGEST_AUTH` | Digest authentication events |
| `BASIC_AUTH_MFA` | Basic auth MFA events |
| `SSO_SAML_MFA` | SAML SSO MFA events |
| `CLIENT_AUTH_CERT_MFA` | Client cert MFA events |
| `SSO_OIDC_MFA` | OpenID Connect SSO MFA events |
### Status values
The `status` query parameter requires UPPERCASE values. The API response returns lowercase values (`success`, `failure`), but query filters require UPPERCASE.
| Query filter value | Description |
|-------|-------------|
| `SUCCESS` | The action completed successfully |
| `FAILURE` | The action failed |
## Step 1: Query recent audit log entries
Start with a broad query to understand the shape of audit log data in your account. This initial request retrieves the 10 most recent entries sorted by timestamp, giving you a representative sample of the fields and values available for filtering.
**Request:**
**curl**
```bash
curl -X GET "https://demo.one.digicert.com/account/api/v1/audit-log?sort=timestamp:desc" \
-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"
# Query parameters
SORT = "timestamp:desc"
response = requests.get(
f"{BASE_URL}/account/api/v1/audit-log",
headers={"x-api-key": ADMIN_API_TOKEN},
params={"sort": SORT}
)
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";
// Query parameters
String sort = "timestamp:desc";
// Send request
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/account/api/v1/audit-log" + "?sort=" + sort))
.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";
// Query parameters
string sort = "timestamp:desc";
// Send request
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", adminApiToken);
var response = await client.GetAsync($"{baseUrl}/account/api/v1/audit-log?sort={sort}");
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Status Code: {(int)response.StatusCode}");
Console.WriteLine(responseBody);
}
}
```
```json
{
"total": 1,
"offset": 0,
"limit": 20,
"items": [
"ITEMS"
]
}
```
The response returns a paginated list with `total`, `offset`, `limit`, and `items` fields. Each item in the `items` array is an audit log entry with fields including `id`, `account`, `resource_type`, `resource_id`, `resource_name`, `action`, `user`, `timestamp`, `description`, and `status`.
Note the following values for use in later steps:
- **`total`** The total number of matching entries. You will use this in [Step 3](#step-3-paginate-through-results) to determine pagination.
- **`resource_type`** Values such as `USER`, `SERVICE_USER`, `APIKEY`, `ACCOUNT`. You will use these to build targeted filters in [Step 2](#step-2-filter-by-date-range-and-resource-type).
- **`action`** Values such as `CREATE`, `UPDATE`, `DELETE`, `LOGIN`. You will use these to build targeted filters in [Step 2](#step-2-filter-by-date-range-and-resource-type).
## Step 2: Filter by date range and resource type
Now that you understand the data shape, narrow your query to a specific reporting period and resource types relevant to your compliance report. Combining `from` and `to` parameters with `resource_types` lets you scope results to security-relevant events within an audit window.
**Request:**
**curl**
```bash
curl -X GET "https://demo.one.digicert.com/account/api/v1/audit-log?from=2026-01-01&to=2026-03-31&resource_types=USER,APIKEY&sort=timestamp:desc" \
-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"
# Query parameters
FROM = "2026-01-01"
TO = "2026-03-31"
RESOURCE_TYPES = "USER,APIKEY"
SORT = "timestamp:desc"
response = requests.get(
f"{BASE_URL}/account/api/v1/audit-log",
headers={"x-api-key": ADMIN_API_TOKEN},
params={"from": FROM, "to": TO, "resource_types": RESOURCE_TYPES, "sort": SORT}
)
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";
// Query parameters
String from = "2026-01-01";
String to = "2026-03-31";
String resourceTypes = "USER,APIKEY";
String sort = "timestamp:desc";
// Send request
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/account/api/v1/audit-log" + "?from=" + from + "&to=" + to + "&resource_types=" + resourceTypes + "&sort=" + sort))
.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";
// Query parameters
string from = "2026-01-01";
string to = "2026-03-31";
string resourceTypes = "USER,APIKEY";
string sort = "timestamp:desc";
// Send request
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", adminApiToken);
var response = await client.GetAsync($"{baseUrl}/account/api/v1/audit-log?from={from}&to={to}&resource_types={resourceTypes}&sort={sort}");
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Status Code: {(int)response.StatusCode}");
Console.WriteLine(responseBody);
}
}
```
Replace the date values with the start and end dates of your compliance reporting period. The `resource_types` parameter accepts a comma-separated list for querying multiple types in a single request.
> **Tip**
>
> To investigate failed operations (potential security incidents), add `status=FAILURE` to your query. To track a specific user's actions, add `user_name` with a partial match string.
```json
{
"total": 1,
"offset": 0,
"limit": 20,
"items": [
"ITEMS"
]
}
```
The response now contains only entries within your date range that involve user or API token resources. Check the `total` field to see how many entries match your filtered query. If `total` exceeds 1000, you will need to paginate through the results in the next step. You'll also need your filter parameters (`from`, `to`, `resource_types`).
## Step 3: Paginate through results
The audit log endpoint caps results at 1000 per request, even if you specify a higher `limit` value. For compliance reports that require a complete data set, you must paginate using `offset` and `limit` to retrieve all matching entries.
**Request (first page):**
**curl**
```bash
curl -X GET "https://demo.one.digicert.com/account/api/v1/audit-log?from=2026-01-01&to=2026-03-31&resource_types=USER,APIKEY&sort=timestamp:desc&offset=0&limit=1000" \
-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"
# Query parameters
FROM = "2026-01-01"
TO = "2026-03-31"
RESOURCE_TYPES = "USER,APIKEY"
SORT = "timestamp:desc"
OFFSET = "0"
LIMIT = "1000"
response = requests.get(
f"{BASE_URL}/account/api/v1/audit-log",
headers={"x-api-key": ADMIN_API_TOKEN},
params={"from": FROM, "to": TO, "resource_types": RESOURCE_TYPES, "sort": SORT, "offset": OFFSET, "limit": LIMIT}
)
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";
// Query parameters
String from = "2026-01-01";
String to = "2026-03-31";
String resourceTypes = "USER,APIKEY";
String sort = "timestamp:desc";
String offset = "0";
String limit = "1000";
// Send request
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/account/api/v1/audit-log" + "?from=" + from + "&to=" + to + "&resource_types=" + resourceTypes + "&sort=" + sort + "&offset=" + offset + "&limit=" + limit))
.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";
// Query parameters
string from = "2026-01-01";
string to = "2026-03-31";
string resourceTypes = "USER,APIKEY";
string sort = "timestamp:desc";
string offset = "0";
string limit = "1000";
// Send request
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", adminApiToken);
var response = await client.GetAsync($"{baseUrl}/account/api/v1/audit-log?from={from}&to={to}&resource_types={resourceTypes}&sort={sort}&offset={offset}&limit={limit}");
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Status Code: {(int)response.StatusCode}");
Console.WriteLine(responseBody);
}
}
```
To retrieve subsequent pages, increment `offset` by the `limit` value. For example, the second page uses `offset=1000`, the third uses `offset=2000`, and so on. Continue until `offset` equals or exceeds the `total` value from the response.
> **Important**
>
> The API silently accepts `limit` values greater than 1000 but caps the actual response to 1000 items. Always use `limit=1000` and paginate with `offset` to ensure you retrieve the complete result set.
```json
{
"total": 1,
"offset": 0,
"limit": 20,
"items": [
"ITEMS"
]
}
```
Each page returns the same `total` value, so you know how many pages to expect. Collect all `items` arrays across pages into a single data set. From the collected entries, extract the unique `user.id` values. You will resolve these to full user details in [Step 4: Resolve user details](#step-4-resolve-user-details). Also extract the unique `account.id` values for resolution in [Step 5: Resolve account details](#step-5-resolve-account-details).
## Step 4: Resolve user details
Audit log entries include a `user` object with `id` and `name` fields that identify who performed each action. For detailed compliance reports, you may need additional user information such as email address, user type, status, and creation date. Use the user ID from audit entries to retrieve full user details.
**Request:**
**curl**
```bash
curl -X GET "https://demo.one.digicert.com/account/api/v1/user/USER_ID" \
-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"
USER_ID = "USER_ID"
response = requests.get(
f"{BASE_URL}/account/api/v1/user/{USER_ID}",
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";
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", 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";
string userId = "USER_ID";
// Send request
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", adminApiToken);
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);
}
}
```
Replace `{user_id}` with a `user.id` value from the audit log entries collected in [Step 3](#step-3-paginate-through-results). Repeat this request for each unique user ID in your data set.
```json
{
"id": "6792e182-4b96-4a2e-9061-14741be4234e",
"email": "jane@example.com",
"status": "ACTIVE",
"access_scope": "account",
"primary_account_id": "d6a3938c-f044-4092-b7f8-1804ae8e4efc",
"created_at": "2021-06-23T08:55:19Z",
"created_by": "5092c936-a5be-4c22-8bec-a649deef2c55",
"user_type": "service",
"friendly_name": "Example service user",
"description": "",
"locale": "en_US",
"applications": [
{
"id": "360348d9-1c3a-49fa-b82d-109ec552fd9f",
"name": "Trust Lifecycle",
"permissions": [
"VIEW_EM_SEAT",
"VIEW_EM_AUDIT_LOG",
"VIEW_EM_CERTIFICATE",
"VIEW_EM_PROFILE"
]
},
{
"id": "c46187a2-243b-41a9-aedc-0518ab1b6cf6",
"name": "IoT Trust",
"permissions": [
"VIEW_IOT_CERTIFICATE",
"VIEW_IOT_ENROLLMENT_PROFILE"
]
},
{
"id": "7e919d8a-07b2-44ee-96a0-9c2e1455e469",
"name": "Document Trust",
"permissions": [
"MANAGE_DSM_VIEW_CERTIFICATE_PROFILES",
"MANAGE_DSM_ADD_VALIDATIONS",
"MANAGE_DSM_VIEW_CERTIFICATE_TEMPLATES",
"MANAGE_DSM_VIEW_VALIDATIONS"
]
},
{
"id": "6510a754-e47b-48c5-88cb-1cd677e801ce",
"name": "Account Manager",
"permissions": [
"MANAGE_AM_ACCOUNT",
"VIEW_AM_AUDIT_LOG"
]
},
{
"id": "e70323fa-6014-42f3-a669-22645606d1fd",
"name": "CA Manager",
"permissions": [
"VIEW_CM_LICENSE"
]
},
{
"id": "a7081787-1dd8-492a-9c90-26ef079a7eb1",
"name": "Software Trust",
"permissions": [
"MANAGE_SM_CERTIFICATE_PROFILE",
"VIEW_SM_CERTIFICATE",
"SIGN_SM_HASH"
]
}
],
"accounts": [
{
"id": "e14c40ed-6827-405f-afc9-c34051dd26e9",
"name": "Example account",
"active": true,
"service_period": {
"from": "2021-05-06",
"to": "2030-05-06"
},
"friendly_identifier": "1234567",
"locale": "en_US"
}
]
}
```
The response includes key fields such as `id`, `user_name`, `first_name`, `last_name`, `email`, `phone`, `status`, `user_type` (either `standard` or `service`), `created_at`, `applications`, and `accounts`. For compliance reports, the `user_type` field is particularly useful for distinguishing human users from service users. The `status` field identifies whether the user is `ACTIVE`, `DELETED`, `PENDING`, or `LOCKED`. The `applications` field shows which DigiCert ONE products and permissions the user has access to. Build a lookup map of user IDs to user details so you can enrich each audit entry in your report. Save the `primary_account_id` field if you need to resolve account details in the next step.
## Step 5: Resolve account details
Audit log entries include an `account` object with `id` and `name` fields that identify the account context for each action. For multi-account environments, you may need additional account information such as service period, status, and administrator details. Use the account ID from audit entries to retrieve full account details.
**Request:**
**curl**
```bash
curl -X GET "https://demo.one.digicert.com/account/api/v1/account/ACCOUNT_ID" \
-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"
ACCOUNT_ID = "ACCOUNT_ID"
response = requests.get(
f"{BASE_URL}/account/api/v1/account/{ACCOUNT_ID}",
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";
String accountId = "ACCOUNT_ID";
// Send request
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/account/api/v1/account/" + accountId))
.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";
string accountId = "ACCOUNT_ID";
// Send request
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", adminApiToken);
var response = await client.GetAsync($"{baseUrl}/account/api/v1/account/{accountId}");
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Status Code: {(int)response.StatusCode}");
Console.WriteLine(responseBody);
}
}
```
Replace `{account_id}` with an `account.id` value from the audit log entries collected in [Step 3](#step-3-paginate-through-results). Repeat this request for each unique account ID in your data set.
```json
{
"id": "ad65390a-0380-4522-bab6-f007c447757a",
"name": "Example account 1",
"active": true,
"service_period": {
"from": "2021-05-26",
"to": "2022-05-26"
},
"friendly_identifier": "7092363",
"admins": [
{
"id": "f7e866c9-768c-4442-adc9-abe2ba4b69d1",
"name": "Jane Doe",
"email": "jane.doe@example.com"
}
],
"sign_in_methods": [
{
"signInMethod": "standard",
"status": "enabled",
"mfaStatus": "disabled",
"clientAuthCertLoginEnabled": false
}
],
"oauth_clients": [],
"locale": "en_US"
}
```
The response includes key fields such as `id`, `name`, `active` status, `service_period`, `friendly_identifier`, `admins`, `auth_config`, `sign_in_methods`, `oauth_clients`, and `locale`. For compliance reports, the `friendly_identifier` provides a human-readable account reference, and `admins` lists the account administrators. Use this data to enrich your audit log entries with full account context, producing a complete compliance report that maps every action to a resolved user and account.
## Common errors and solutions
For general API errors (authentication, rate limits), see [Error handling and rate limits](https://dev.digicert.com/md/get-started/error-handling-rate-limits.md).
### invalid_input_field
```json
{
"errors": [
{
"code": "invalid_input_field",
"message": "Invalid from [2026/01/01]."
}
]
}
```
Use `YYYY-MM-DD` format for the `from` and `to` query parameters. Separate date components with hyphens, not slashes or other delimiters. Example: `from=2026-01-01`.
### not_found
```json
{
"errors": [
{
"code": "not_found",
"message": "User not found."
}
]
}
```
Handle `404` responses gracefully when resolving user details in [Step 4: Resolve user details](#step-4-resolve-user-details). The `user_id` in the audit log entry might reference a deleted user. Record the user as deleted or unknown in your report. The audit log entry's `user.name` field still contains the username at the time of the action.
### Empty results with valid filters
```json
{
"total": 0,
"offset": 0,
"limit": 1000,
"items": []
}
```
Verify your filter values use exact UPPERCASE matches for the `resource_types` and `action` parameters (for example, `resource_types=USER`, `action=CREATE`). Check that your `from`/`to` date range covers a period with actual account activity. Run a broad query ([Step 1](#step-1-query-recent-audit-log-entries)) first to confirm data exists, then progressively add filters.
## What's next?
Now that you have built an audit log query workflow for compliance reporting, you can:
- **Automate periodic reports**: Schedule your audit log queries to run on a recurring basis (daily, weekly, quarterly) to generate compliance reports automatically for SOC 2 or PCI DSS audits.
- **Monitor for security events**: Filter by `status=FAILURE` and `action=LOGIN_ERROR` to detect failed sign-in attempts and potential security incidents in near real-time.
- **Track API token lifecycle**: Filter by `resource_types=APIKEY` to monitor token creation, deletion, and modification events across your organization.
- **Extend to other DigiCert ONE managers**: Each DigiCert ONE manager maintains its own audit logs. Apply the same query patterns to audit logs in Private CA, Device Trust, and other managers for organization-wide compliance visibility.