Skip to content

Integration changelog

The API has one current contract. URLs carry no version. The info.version field in the OpenAPI schema identifies the contract with semantic versioning: the minor version rises for additions and the major version for a breaking change. Every change is listed on this page with its date.

These can ship at any time, recorded here:

  • New endpoints, operations and scopes.
  • New optional request fields.
  • New response fields, including fields inside nested objects.
  • New values in fields that list a fixed set of values, such as a report status.
  • New webhook event types, and new fields in webhook payloads.
  • New error codes, response headers and _url links.
  • Ignore response and webhook fields you do not recognise.
  • Handle an unknown value in a fixed-value field without failing.
  • Acknowledge webhook events whose type you do not handle with a 2xx response, and ignore them.
  • Follow _url links and Link headers instead of building URLs.
  • Treat IDs and cursors as opaque strings.

A breaking change removes or renames a field, endpoint or event type, changes a field’s type or meaning, makes an optional request field required, or asks for a different scope. The confidential-data boundary never changes: no version adds report content to the API.

We avoid breaking changes. If one is needed:

  1. The new behaviour ships next to the old one.
  2. The old one is marked deprecated in the OpenAPI schema, and its responses carry Deprecation and Sunset headers (RFC 9745, RFC 8594).
  3. We email everyone whose tokens still use it: the owner of a personal token, or the administrators of the organisation that owns an organisation token.
  4. It keeps working for at least six months after that email.

If breaking changes ever become frequent, new behaviour will be opt-in through an EthicsPortal-Version date header. Requests without the header will keep the contract they use today.

10 November 2026. An AI assistant can connect to EthicsPortal through the MCP server and call the API’s operations as tools, after a person approves the connection with OAuth. It started as a pilot for chosen organisations. Existing API tokens and webhooks work as before. In the audit trail, an entry written through a connection has the actor kind mcp.

11 November 2026. A person with no account or no organisation can start from an assistant: they sign up on the consent screen, and the assistant creates their first organisation. The same day, the MCP server opened to every organisation that has API access.

Section titled “1.1.0: feedback from any token, and a feedback link in every error”

Released on 10 November 2026.

  • Product feedback needs no scope. Any valid token can send it, and an organisation token can send it too. The feedback:write scope no longer exists. It was removed from the tokens that held it, and their other scopes are unchanged.
  • Every error response carries error.feedback_url, the address of the feedback operation. Errors.

1.0.1: audit trail entries appear after a minute

Section titled “1.0.1: audit trail entries appear after a minute”

Released on 10 November 2026. Both audit trail endpoints now return an entry once it is a minute old. Before, an entry whose write finished late could appear behind a timestamp a collector had already passed, and resuming with created_after skipped it. Read the audit trail.

Version 1.0.0, released on 10 November 2026. The first API and webhook contract, available to every organisation.

  • Organisation, whistleblowing channel and report metadata reads.
  • Personal tokens that act with their owner’s current role in every organisation, and organisation tokens that belong to one organisation and keep working when staff change.
  • Fixed scopes per token: reports:read, channel:read, channel:write, webhooks:read, webhooks:write, and organizations:create for personal tokens. A missing scope returns insufficient_scope and names it in WWW-Authenticate.
  • Lists are objects with data and next_cursor, so they can gain fields without breaking clients.
  • Idempotency-Key on every POST makes retries after a lost response safe.
  • The audit trail, members, invitations and organisation renaming, with audit_log:read, members:read, members:write and organizations:write.
  • Document downloads (documents:read), billing status (billing:read), and accepting or declining your own invitations with a personal token (invitations:respond).
  • Product feedback with a personal token (feedback:write).
  • Subscription checkout and billing portal links (billing:write), completed by a person on Stripe’s pages.
  • ETag on every JSON read with If-None-Match support, and _url links so clients can navigate from /identity.json without building URLs.
  • Organisation creation and channel configuration with strict JSON writes and field-only validation errors. New organisations still need their DPA accepted in the application.
  • Organisation-owned, signed lifecycle and deadline webhooks, with retries, stable event IDs and scheduled retry times in delivery history. Everything on the webhook screen is also available through the API.
  • Token activity with separately sampled successful requests and refusals, plus a limit of 20 active tokens per user and per organisation.
  • Webhook failure warnings with administrator notifications. Failures do not automatically disable webhooks.
  • Explicit exclusion of report content, identities, attachments, messages, notes, category, closure outcome and retaliation.