Integration changelog
Versioning and compatibility
Section titled “Versioning and compatibility”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.
Changes that do not break clients
Section titled “Changes that do not break clients”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
_urllinks.
Build your client to tolerate them
Section titled “Build your client to tolerate them”- Ignore response and webhook fields you do not recognise.
- Handle an unknown value in a fixed-value field without failing.
- Acknowledge webhook events whose
typeyou do not handle with a2xxresponse, and ignore them. - Follow
_urllinks andLinkheaders instead of building URLs. - Treat IDs and cursors as opaque strings.
Breaking changes
Section titled “Breaking changes”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:
- The new behaviour ships next to the old one.
- The old one is marked deprecated in the OpenAPI schema, and its responses carry
DeprecationandSunsetheaders (RFC 9745, RFC 8594). - 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.
- 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.
MCP server
Section titled “MCP server”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.
1.1.0: feedback from any token, and a feedback link in every error
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:writescope 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.
Initial contract
Section titled “Initial contract”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, andorganizations:createfor personal tokens. A missing scope returnsinsufficient_scopeand names it inWWW-Authenticate. - Lists are objects with
dataandnext_cursor, so they can gain fields without breaking clients. Idempotency-Keyon every POST makes retries after a lost response safe.- The audit trail, members, invitations and organisation renaming, with
audit_log:read,members:read,members:writeandorganizations: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. ETagon every JSON read withIf-None-Matchsupport, and_urllinks so clients can navigate from/identity.jsonwithout 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.