# Set up organisations and whistleblowing channels

Source: https://ethicsportal.eu/developers/organisation-setup/

Setup uses two write scopes. Neither is preselected: choose them when you create a token. Scopes cannot be added to an existing token.

## Choose the scopes

* `organizations:create` creates organisations. Only personal tokens can hold it, because a new organisation belongs to a person: you become its owner and administrator.
* `channel:write` reads and changes channel configuration. On a personal token it works only where you are a current administrator; it never promotes a member or viewer. On an organisation token, an administrator granted it when creating the token, so the scope alone applies.

Creating a token requires fresh authentication. Tokens cannot issue tokens or accept agreements. Webhooks, invitations and billing links each have their own scope. [Authentication and permissions](https://ethicsportal.eu/developers/authentication/).

## Create an organisation

Your token owner must have at least one active membership and must have accepted the current account terms. An [assistant connection](https://ethicsportal.eu/developers/mcp/#start-without-an-organisation) is the exception: a person with no organisation can create their first one through it.

```
curl --fail-with-body \
  -X POST \
  -H "Authorization: Bearer $ETHICSPORTAL_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" \
  --data '{"organization":{"name":"Example organisation"}}' \
  "$ETHICSPORTAL_ORIGIN/organizations.json"
```

A `201` response contains:

```
{
  "id": "gHiJkl",
  "name": "Example organisation",
  "membership_id": "mAbCde",
  "channel": { "id": "AB12CD34", "active": false }
}
```

The token owner becomes the organisation owner and an administrator. Its default whistleblowing channel is created automatically. Treat all IDs as strings. Save `id` as `ETHICSPORTAL_ORGANIZATION_ID` and `membership_id` for appointing yourself as compliance officer.

Creation does **not** start a subscription or accept the DPA. The new organisation is reachable through the API at once, but its owner must accept the current organisation agreement in EthicsPortal before configuration requests can succeed. The `Location` response header points to the organisation’s web page, which requires a separate browser session.

Send an `Idempotency-Key` header with each creation, as in the example. If the response is lost, repeat the request with the same key: you get the first response back instead of a second organisation. Without a key, a lost response may still mean the organisation was created, so check before retrying. [Safe retries](https://ethicsportal.eu/developers/pagination-and-errors/#safe-retries). Names need not be unique. Organisation creation allows up to ten attempts per user per minute, shared across tokens.

## Read the configuration

```
curl --fail-with-body \
  -H "Authorization: Bearer $ETHICSPORTAL_TOKEN" \
  "$ETHICSPORTAL_ORIGIN/organizations/$ETHICSPORTAL_ORGANIZATION_ID/whistleblower/portal/configuration.json"
```

This privileged resource returns company details, channel settings, the compliance officer’s obfuscated membership ID, public reporting form URL, verification state, `missing_fields` and derived `active` state. It requires `channel:write` even for GET. Ordinary channel metadata remains limited to its identifier, active state and public form URL.

## Configure the channel

Send only the fields you want to change. Use native JSON booleans and numbers. Unknown attributes, nested values, additional top-level objects and query parameters are rejected with `400 invalid_request`.

```
curl --fail-with-body \
  -X PATCH \
  -H "Authorization: Bearer $ETHICSPORTAL_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"portal":{
    "legal_name":"Example company",
    "country_code":"FR",
    "registration_number":"EXAMPLE-123",
    "address":"1 Example Street",
    "employee_range":"1-49",
    "industry":"professional_scientific_services",
    "retention_months":60,
    "compliance_officer_id":"mAbCde",
    "social_dialogue_consulted":true,
    "voice_recording_enabled":false,
    "email_intake_enabled":false,
    "brand_color":"#123456"
  }}' \
  "$ETHICSPORTAL_ORIGIN/organizations/$ETHICSPORTAL_ORGANIZATION_ID/whistleblower/portal/configuration.json"
```

Additional optional fields are `phone_number` and `website`. [The API reference](https://ethicsportal.eu/developers/api/) lists types and supported values. Use the `membership_id` returned by creation to appoint yourself. Other officers must already be active administrators in the same organisation; obtain their obfuscated membership ID from your authorised team workflow. Raw database IDs are rejected.

Settings obey the same model rules as the application:

* Verified company details are locked. The API cannot grant or remove verification.
* Retention must be an offered value and meet the country’s minimum. Change the country and retention together when needed.
* Compliance officers must be active administrators in the organisation.
* Removing required information, including setting the compliance officer to `null`, can make the channel inactive.
* `active` is derived from complete required information and existing subscription or granted access. It cannot be set directly. A successful save does not guarantee activation.

The API does not create missing channels during GET or PATCH. A normal organisation creation already creates one; a missing channel returns `404`.

## Handle validation errors

A model validation failure returns `422` and the affected field names, without echoing submitted values:

```
{"error":{"code":"validation_failed","fields":["retention_months"],"feedback_url":"https://secure.ethicsportal.eu/me/feedback.json"}}
```

`base` indicates a record-level restriction, such as locked verified company details. A non-administrator compliance officer can be reported as `compliance_officer`. No partial settings are saved on validation failure. [Errors and rate limits](https://ethicsportal.eu/developers/pagination-and-errors/#errors).

All report-content exclusions continue to apply. There is no report submission, report mutation or agreement-acceptance API. After setup, the API also manages [webhooks](https://ethicsportal.eu/developers/webhooks/#manage-webhooks-through-the-api), and sends invitations and creates subscription checkout links: [Administration](https://ethicsportal.eu/developers/administration/). Changing a member’s role and removing a member stay in the web application.
