Skip to content

List a report's audit trail

GET
/organizations/{organization_id}/whistleblower/reports/{id}/audit-log.json
curl --request GET \
--url 'https://secure.ethicsportal.eu/organizations/example/whistleblower/reports/example/audit-log.json?limit=50' \
--header 'Authorization: Bearer <token>'

One report’s audit trail. Omits anything a reporter did and entries about messages, notes and retaliation, consistent with the data boundary. Entries carry no change details, IP addresses or email addresses. Oldest first. A personal token needs access to the report. Entries appear once they are a minute old, so a collector resuming with created_after cannot skip one that committed late.

organization_id
required
string

Obfuscated organisation ID returned by identity.

id
required
string

Obfuscated report ID; not the reporter access code.

limit
integer
default: 50 >= 1 <= 100
cursor
string

Follow the Link response header unchanged. Signed cursor expires after one hour.

created_after
string format: date-time

Exclusive lower bound; resume a log collector from the last entry it stored.

If-None-Match
string

The ETag of a response you already hold. If nothing changed, the response is 304 Not Modified with no body. It still counts toward rate limits and, where reads are audited, the audit trail.

Audit trail entries for the report.

Media typeapplication/json
object
data
required
Array<object>
<= 100 items
object
id
required
string
action
required

Stable action name, such as whistleblower.report.viewed or invitation.created.

string
actor
required
object
kind
required
string
Allowed values: member system scim sso api mcp admin
name
required
string | null
membership_id
required
string | null
subject
required
object
type
required
string
Allowed values: report channel organization membership invitation webhook organization_token personal_token data_export other
id
required
string
created_at
required
string format: date-time
next_cursor
required

Pass as the cursor parameter for the next page; null on the last page. The Link header carries the same next page.

string | null

Example

{
"data": [
{
"id": "hIjKlm",
"action": "whistleblower.report.viewed",
"actor": {
"kind": "member",
"name": "Anna Novak",
"membership_id": "nOpQrs"
},
"subject": {
"type": "report",
"id": "aBcDef"
},
"created_at": "2026-11-09T10:00:00Z"
}
],
"next_cursor": null
}
ETag
string

Weak validator of this response body. Send it back as If-None-Match.

Not modified since the ETag sent in If-None-Match. No body.

Invalid query, body or cursor

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: invalid_token forbidden insufficient_scope not_found invalid_request agreement_required rate_limited idempotency_key_reused idempotency_key_in_progress not_retryable channel_inactive invitation_unavailable already_subscribed no_subscription
feedback_url
required

Where to tell EthicsPortal what went wrong: POST product feedback here with the same token.

string format: uri

Example

{
"error": {
"code": "invalid_request",
"feedback_url": "https://secure.ethicsportal.eu/me/feedback.json"
}
}

Missing, unknown, expired or revoked token

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: invalid_token forbidden insufficient_scope not_found invalid_request agreement_required rate_limited idempotency_key_reused idempotency_key_in_progress not_retryable channel_inactive invitation_unavailable already_subscribed no_subscription
feedback_url
required

Where to tell EthicsPortal what went wrong: POST product feedback here with the same token.

string format: uri

Example

{
"error": {
"code": "invalid_token",
"feedback_url": "https://secure.ethicsportal.eu/me/feedback.json"
}
}

The token lacks the required scope (WWW-Authenticate names it), the user’s role does not allow the action, or an agreement must be accepted in the web application

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: invalid_token forbidden insufficient_scope not_found invalid_request agreement_required rate_limited idempotency_key_reused idempotency_key_in_progress not_retryable channel_inactive invitation_unavailable already_subscribed no_subscription
feedback_url
required

Where to tell EthicsPortal what went wrong: POST product feedback here with the same token.

string format: uri

Example

{
"error": {
"code": "insufficient_scope",
"feedback_url": "https://secure.ethicsportal.eu/me/feedback.json"
}
}

Organisation or resource missing or inaccessible, or API access suspended

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: invalid_token forbidden insufficient_scope not_found invalid_request agreement_required rate_limited idempotency_key_reused idempotency_key_in_progress not_retryable channel_inactive invitation_unavailable already_subscribed no_subscription
feedback_url
required

Where to tell EthicsPortal what went wrong: POST product feedback here with the same token.

string format: uri

Example

{
"error": {
"code": "not_found",
"feedback_url": "https://secure.ethicsportal.eu/me/feedback.json"
}
}

Rate limited; retry after the Retry-After interval

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: invalid_token forbidden insufficient_scope not_found invalid_request agreement_required rate_limited idempotency_key_reused idempotency_key_in_progress not_retryable channel_inactive invitation_unavailable already_subscribed no_subscription
feedback_url
required

Where to tell EthicsPortal what went wrong: POST product feedback here with the same token.

string format: uri

Example

{
"error": {
"code": "rate_limited",
"feedback_url": "https://secure.ethicsportal.eu/me/feedback.json"
}
}