Skip to main content
Solved

Audit/History For Exports via API Key

  • May 5, 2026
  • 2 replies
  • 176 views

Forum|alt.badge.img

Hi Pigment Community,

Is there a way to see information about data exports performed via an API export key?

For imports, Pigment provides good traceability: when using an API import key, the application shows which assigned user performed the import (e.g. via the Block updates view).

I’m looking for something similar on the export side:

  • Visibility that an export was triggered via an API export key
  • Ideally, being able to see which user the key is assigned to, or some form of audit/logging for API exports

Is this currently possible, or is there a recommended workaround?

Thanks in advance!

Best answer by Veniamin

Hi Niklas,

You can get both of those, but not from the UI. It all lives in the Audit Logs API.

The event you want is `DataExported`. Per the KB, any export from a Pigment block through the Export API is logged as this event; UI exports only produce it for Dimension and Transaction Lists. The payload gives you the block, the application, and the entity type.

When the export came from an API key, the `actor` on the event doesn't hold a user. It holds the key:

```json
"actor": {
  "api": {
    "apiKeyId": "1111...",
    "apiKeyName": "My Export API KEY"
  }
}
```

So out of the box you see the key, not the person. That's the gap you're describing.

The person is recoverable with one join. API key lifecycle events (`APIKeyCreated`, `APIKeyRenamed`, `APIKeyRenewed`, `APIKeyRevoked`) carry the key's `id`, its `type` (Export / Import / SecurityAudit / UserProvisioning), `expirationDate`, `ownerId`, and `actOnBehalfOfKeyOwner`. So:

```
DataExported        → actor.api.apiKeyId
APIKeyCreated       → payload.id, payload.ownerId, payload.actOnBehalfOfKeyOwner
any event by that user → actor.user.id + actor.user.email
```

`ownerId` is a user id, so you need that last hop to turn it into an email. And `actOnBehalfOfKeyOwner` is the field that literally answers "is this key running as that user".

Three things that bit me when I built this:

The lookback is 180 days. If a key was created before that and hasn't been renamed or renewed since, its lifecycle event has aged out and the join returns nothing. I keep a small static key-to-owner mapping as a fallback and only rely on the audit join for recent keys.

Put the owner and the purpose in the key name. `apiKeyName` is on every single event with no join at all, so a convention like `EXPORT_FINANCE_jdoe` gets you most of the traceability for free.

The Audit Logs API is on the Enterprise plan, and only a Security Admin can create the key.

On the mechanics: `GET https://pigment.app/api/audit/v1/events?ingestedSince=...`, 1000 events per page, cursor pagination via `nextEventsCursor`, dedupe on `eventId`, and keep a high-water mark with a few hours of overlap between runs so nothing slips through.

 

Docs:
https://kb.pigment.com/docs/audit-logs-api-event-types
https://kb.pigment.com/docs/call-audit-logs-api

2 replies

  • May 6, 2026

You can leverage the audit events api


Veniamin
Apprentice Helper
Forum|alt.badge.img
  • Apprentice Helper
  • Answer
  • July 30, 2026

Hi Niklas,

You can get both of those, but not from the UI. It all lives in the Audit Logs API.

The event you want is `DataExported`. Per the KB, any export from a Pigment block through the Export API is logged as this event; UI exports only produce it for Dimension and Transaction Lists. The payload gives you the block, the application, and the entity type.

When the export came from an API key, the `actor` on the event doesn't hold a user. It holds the key:

```json
"actor": {
  "api": {
    "apiKeyId": "1111...",
    "apiKeyName": "My Export API KEY"
  }
}
```

So out of the box you see the key, not the person. That's the gap you're describing.

The person is recoverable with one join. API key lifecycle events (`APIKeyCreated`, `APIKeyRenamed`, `APIKeyRenewed`, `APIKeyRevoked`) carry the key's `id`, its `type` (Export / Import / SecurityAudit / UserProvisioning), `expirationDate`, `ownerId`, and `actOnBehalfOfKeyOwner`. So:

```
DataExported        → actor.api.apiKeyId
APIKeyCreated       → payload.id, payload.ownerId, payload.actOnBehalfOfKeyOwner
any event by that user → actor.user.id + actor.user.email
```

`ownerId` is a user id, so you need that last hop to turn it into an email. And `actOnBehalfOfKeyOwner` is the field that literally answers "is this key running as that user".

Three things that bit me when I built this:

The lookback is 180 days. If a key was created before that and hasn't been renamed or renewed since, its lifecycle event has aged out and the join returns nothing. I keep a small static key-to-owner mapping as a fallback and only rely on the audit join for recent keys.

Put the owner and the purpose in the key name. `apiKeyName` is on every single event with no join at all, so a convention like `EXPORT_FINANCE_jdoe` gets you most of the traceability for free.

The Audit Logs API is on the Enterprise plan, and only a Security Admin can create the key.

On the mechanics: `GET https://pigment.app/api/audit/v1/events?ingestedSince=...`, 1000 events per page, cursor pagination via `nextEventsCursor`, dedupe on `eventId`, and keep a high-water mark with a few hours of overlap between runs so nothing slips through.

 

Docs:
https://kb.pigment.com/docs/audit-logs-api-event-types
https://kb.pigment.com/docs/call-audit-logs-api