Skip to content

Rotate a webhook's signing secret

POST
/organizations/{organization_id}/webhooks/{webhook_id}/rotate.json
curl --request POST \
--url https://secure.ethicsportal.eu/organizations/example/webhooks/example/rotate.json \
--header 'Authorization: Bearer <token>'

Replace the signing secret immediately; there is no overlap period. Pending deliveries from the previous secret are cancelled. The response contains the new secret once. A personal token also needs its user to be a current administrator of the organisation.

organization_id
required
string

Obfuscated organisation ID returned by identity.

webhook_id
required
string
Idempotency-Key
string
>= 1 characters <= 255 characters /^[\x21-\x7e]+$/

Recommended on every POST. Retrying with the same key and the same request within 24 hours returns the first response (with Idempotent-Replayed: true) instead of acting twice. Only successful responses and validation errors are stored; any other outcome releases the key. Reusing a key with a different request returns 409 idempotency_key_reused; a retry while the first request is still running returns 409 idempotency_key_in_progress. Keys are scoped to the token.

The webhook with its new secret.

Media typeapplication/json
object
id
required
string
name
required
string
<= 100 characters
url
required

The destination EthicsPortal sends events to, as in Stripe’s API. Other *_url fields are links within this API.

string format: uri
enabled
required
boolean
events
required
Array<string>
>= 1 items unique items
Allowed values: report.created report.acknowledged report.feedback_given report.closed report.reopened report.assignment_changed report.due_soon report.overdue
failing_since
required

Set when a delivery failed permanently or exhausted its retries; cleared by a later success or a configuration change.

string | null format: date-time
created_at
required
string format: date-time
updated_at
required
string format: date-time
secret
required

Signing secret. Returned only when created or rotated; store it immediately.

string
deliveries_url
required
string format: uri

Example

{
"id": "pQrStu",
"name": "Case dashboard",
"url": "https://receiver.example/ethicsportal",
"enabled": true,
"events": [
"report.created",
"report.overdue"
],
"failing_since": null,
"created_at": "2026-11-09T10:00:00Z",
"updated_at": "2026-11-09T10:00:00Z",
"secret": "ep_whsec_example",
"deliveries_url": "https://secure.ethicsportal.eu/organizations/gHiJkl/webhooks/pQrStu/deliveries.json"
}

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"
}
}

This Idempotency-Key was already used with a different request, or its first request is still running

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": "idempotency_key_reused",
"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"
}
}