# Get a partner's audit log Returns a paginated, filterable audit trail of authentication activity for a partner

`GET /api/configuration/admin/partners/{id}/audit-log`

- **Success:** `200 OK`
- **Products:** not restricted by product
- **Features:** Gladstone Admin Areas (`ADMIN`)

HTML version: [Get a partner's audit log Returns a paginated, filterable audit trail of authentication activity for a partner](https://support.gladstonesoftware.cloud/reference/configuration/get-a-partners-audit-log-returns-a-paginated-filterable-audit-trail-of-authentic)

## Overview

Returns a page of authentication events recorded against a partner integration. Each entry records the API key used, the action attempted, the masked member email where one was involved, the caller's IP address, the HTTP status returned and the UTC timestamp. Newest first.

**The audit trail is written asynchronously and can lose entries under load.** An event you have just caused may take a few seconds to appear. At most 2,000 events can be waiting to be recorded; beyond that the oldest are dropped, and an event that fails to record is not retried. Treat the log as a very good record, not as a guaranteed-complete one — it is not a substitute for your own request logging if you need exactness.

**An unknown partner id is not an error.** There is no check that the partner exists, so a wrong id returns `200` with an empty `items` array and `totalCount` of `0` — exactly the same shape as a real partner with no activity. Confirm the partner exists separately before concluding it has never been used.

Entries are linked to the partner through the API key that produced them, so the log spans every key the partner has ever had, including keys since revoked or renewed. Revoking a key does not remove its history.

## Endpoint

`GET {base_url}/api/configuration/admin/partners/{id}/audit-log`

`{base_url}` is the environment URL issued to your integration. See [Authenticating with Gladstone APIs](../../guides/authenticating-with-gladstone-apis.md).

## Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | integer (int32) | Yes | The unique identifier of the partner whose audit log is being requested. |

## Query parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `page` | integer (int32) | No | 1-based page number for paginated results. Defaults to 1. Unlike `pageSize` it is not range-checked, and a page beyond the end simply returns an empty `items` array with the real `totalCount`. |
| `pageSize` | integer (int32) | No | Number of audit entries per page. Must be between 1 and 200. Defaults to 20. It is the only validated parameter: `0`, a negative number or anything above 200 returns `400`. It is echoed back in the response and drives `totalPages`. |
| `action` | integer (int32) | No | Restricts the page to one kind of event. Accepts either the numeric value or the name: `0` / `MemberLogin` for a member signing in through the partner, `1` / `TokenRefresh` for a token being refreshed, `2` / `ApiToken` for the partner obtaining a token with its API key. Omit it, or send null, for all three. A value that is neither a valid name nor a valid number returns `400`. |
| `from` | string (date-time) | No | Lower bound for the audit timestamp, inclusive, interpreted as UTC. Omit for no lower bound. Combine with `to` for a window; the two are applied independently, so an inverted pair simply matches nothing and returns an empty page rather than an error. |
| `to` | string (date-time) | No | Upper bound for the audit timestamp, **inclusive** — an entry stamped exactly at `to` is returned. Omit for no upper bound. Because it is inclusive, paging forward by using the previous window's last `createdAtUtc` as the next `from` will return that entry twice. |

## Sample request

```bash title="cURL"
curl -X GET '{base_url}/api/configuration/admin/partners/{id}/audit-log' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true'
```

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `items` | array of object | The audit entries on this page, ordered by `createdAtUtc` descending — newest first. Empty when the partner has no matching activity, when the page is beyond the end, or when the partner id does not exist at all; the array is always present rather than null. |
| `items[].id` | integer (int64) | The audit entry's own identifier. It increases as entries are recorded, but recording is asynchronous, so it is not a reliable ordering key — sort by `createdAtUtc`. There is no endpoint that retrieves a single entry by this value. |
| `items[].partnerApiKeyId` | integer (int32) | Which of the partner's API keys produced the event. Use it to tell activity on a rotated-out key from activity on the current one; entries survive revocation, so an old key's id keeps appearing in history. |
| `items[].environmentId` | integer (int32) | The tenant environment the event was recorded against. Null for events where no environment was resolved, which is why a global partner's log can carry entries from several environments. |
| `items[].action` | string | What was attempted, as the name rather than the number: `MemberLogin`, `TokenRefresh` or `ApiToken`. Note the asymmetry with the `action` query parameter, which also accepts `0`, `1` and `2`. |
| `items[].memberEmail` | string | The member involved, **masked when recorded**: the first character, then `***`, then everything from the `@` onwards — `alice@example.com` is recorded as `a***@example.com`. The unmasked address is never kept, so this cannot be used to identify a member exactly, only to correlate. A value with no `@` is recorded unchanged. Null for events with no member, such as `ApiToken`. |
| `items[].ipAddress` | string | The caller's IP address as seen by Gladstone when the attempt was made. Useful for spotting a single source behind a run of failures. |
| `items[].httpStatusCode` | integer (int32) | The status the authentication attempt returned. Both successes and failures are audited, so this is the field that separates them — a run of `401`s against one `ipAddress` is the signal this endpoint exists for. |
| `items[].createdAtUtc` | string (date-time) | When the entry was recorded, stamped in UTC at that point, not at the moment of the event. Under load that can be marginally later than the event itself. This is the field `from` and `to` filter on, and the field results are ordered by. |
| `page` | integer (int32) | The page number echoed back from the request, not a value derived from the data — it is returned unchanged even when it is past the end and `items` is empty. |
| `pageSize` | integer (int32) | The page size echoed back from the request. `items` can be shorter than this on the last page, but never longer. |
| `totalCount` | integer (int32) | The number of entries matching the filters, counted before paging. Compare it with `page` × `pageSize` to decide whether to fetch more. Because the log is written asynchronously, this can change between two calls made seconds apart. |
| `totalPages` | integer (int32) | The number of pages the filtered set spans, calculated as `totalCount` divided by `pageSize` and rounded up. It is `0` when nothing matches. |

## Sample response

```json title="200 OK"
{
  "items": [
    {
      "id": 12345,
      "partnerApiKeyId": 12345,
      "environmentId": 12345,
      "action": "string",
      "memberEmail": "member@example.com",
      "ipAddress": "string",
      "httpStatusCode": 1,
      "createdAtUtc": "2026-08-14T19:00:00Z"
    }
  ],
  "page": 1,
  "pageSize": 1,
  "totalCount": 1,
  "totalPages": 1
}
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | `pageSize` is `0`, negative, or above 200 — the body is the plain string `pageSize must be between 1 and 200.`. Note the endpoint applies no equivalent check to `page`. |
| `400` | Bad request | A query parameter could not be parsed — `action` that is neither a valid name nor `0`, `1` or `2`, or `from`/`to` that is not a parsable date-time. The body is a validation error object keyed by field name rather than a plain string. |
| `503` | Service unavailable | Not returned by this endpoint. |
