> ## Documentation Index
> Fetch the complete documentation index at: https://docs.niadra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Parties and approvals

> The legal persons of a project, the controller that approves by a link with a code in its e-mail, the operator transfer, the impact report, the access review and emergency access.

A Niadra project is operated by a tenant, but its data may belong to another company: the brand hires a consultancy that integrates and runs the agents; the clinic network outsources its service; the insurer runs on a partner's platform. The law calls one the **controller** and the other the **operator** (the processor), and the controller must decide what is done with its data without signing in to the operator's Console. The account model names those parties and takes each decision to the controller by a link, with a code in its DPO's e-mail.

This page is about the legal persons that answer for a project. The organizations that are subjects of memory, customers and partners with a context of their own, are in [Accounts and partners](/en/concepts/accounts).

## Where it applies

The account model is not a space feature: the routes live on the [control API](/en/api#authentication), with a Console person token, and apply to every tenant. A project whose controller is the tenant itself changes in nothing: no approval is asked, and the access review never falls due. In the Console, the Project and controller screen, of the `security` role, and the Companies screen appear when the control plane serves the account model.

Links and codes leave by e-mail. When the e-mail cannot be sent, an approval request answers 503 `unavailable`, and no link is left working.

## Legal entities

A **legal entity** ([`POST /v1/legal-entities`](/en/api/control/legal-entities-create)) is a company registered once per country and registry number, with its name and the e-mail of its data protection officer. The registry number is kept as a keyed hash and comes back masked; the DPO e-mail is sealed and never shown back: it is where the links and codes go. The same number with the same DPO answers the entity that already exists; with another DPO, 409. [`GET /v1/legal-entities`](/en/api/control/legal-entities) lists the tenant's.

## The parties of a project

A **party** ([`POST /v1/projects/{project_id}/parties`](/en/api/control/parties-add)) links a legal entity to a project with a role: `controller`, `operator` or `sub_operator`, and, when the party uses the Console through a tenant, that tenant's id. The operating tenant adds its controller; from then on, adding an operator or a sub-operator to the project answers 409 `controller_approval_required` until the controller approves `add:<role>:<entity id>`, and ending an operator ([`POST .../parties/{party_id}/end`](/en/api/control/party-end)) waits for the approval of `end:<party id>`. [`GET /v1/projects/{project_id}/parties`](/en/api/control/parties) lists the parties, with since when and until when.

## Approvals by link

An **approval** ([`POST /v1/approvals`](/en/api/control/approvals-create)) is a request to the project's controller. Niadra sends a single-use link to its DPO's e-mail, and the API answer never carries it. The request has a kind and a subject:

| Kind | What the controller approves | `subject_ref` |
| - | - | - |
| `purposes` | A diff that widens the space's purposes | The pending diff's id |
| `policy_loosening` | A diff that loosens the access policy | The pending diff's id |
| `retention` | A diff that extends a retention | The pending diff's id |
| `operators` | An operator or sub-operator joining or leaving | `add:<role>:<entity id>` or `end:<party id>` |
| `transfer` | The project's operation passing to another tenant | The receiving tenant's id |
| `access_review` | The operators' access stays as it is | Ignored |
| `ripd` | An impact report, by its hash | The purpose |

`emergency_access` is the eighth kind, and is never requested: it is how an [emergency access](#emergency-access) is recorded. Each approval has a `document_hash`, the SHA-256 of the canonical JSON of what the controller approves, and a status: `pending`, `approved`, `rejected` or `expired`. [`GET /v1/projects/{project_id}/approvals`](/en/api/control/approvals) lists a project's.

### The link, step by step

The approval page is public, and the code from the e-mail is its credential. The link's token travels only in request bodies, never in the URL of an API call.

1. [`POST /v1/approvals/link/preview`](/en/api/control/approval-link-preview) shows what is asked, by which tenant, for which project and until when, before any code. An unknown, used or expired link answers 401 alike.
2. [`POST /v1/approvals/link/code`](/en/api/control/approval-link-code) sends a six-digit code to the DPO's e-mail, valid for 15 minutes: at most five codes per link and one a minute, or 429.
3. [`POST /v1/approvals/link/open`](/en/api/control/approval-link-open) opens, with the code, the document to decide on: the summary and, for a `ripd`, the report in Markdown. A wrong code is 401 and counts; the fifth wrong code closes the link.
4. [`POST /v1/approvals/link/decide`](/en/api/control/approval-link-decide) approves or refuses, once, with an optional note. The link stops working, and the decision becomes a receipt in the chain of the project's spaces.

## What waits for the controller

In a project whose controller is not the tenant, a configuration diff that widens purposes, loosens the policy or extends a retention does not take effect when it is approved in the Console: it waits for the controller's approval, requested with the diff's id. The control plane checks this when the diff is submitted and again when it is approved. The same holds for an operator joining or leaving.

## Operator transfer

A **transfer** ([`POST /v1/projects/{project_id}/transfer`](/en/api/control/project-transfer)) passes the project's operation to the caller's tenant, on the controller's `transfer` approval, whose subject is that tenant's id. The space databases stay where they are, so the memory continues without a copy. The old source keys keep working for `grace_hours` (72 by default; 0 cuts them at once) and expire at `grace_until`; the answer says how many were retired and, per space, the webhook endpoints whose secrets the new operator must turn before then, because an endpoint still signing with an old secret stops receiving when the grace period ends. With `operator_entity_id`, the new operator's legal entity joins as the project's operator. [`GET /v1/projects/{project_id}/transfers`](/en/api/control/transfers) lists the transfers.

## Impact report

[`GET /v1/projects/{project_id}/ripd`](/en/api/control/project-ripd) generates the data protection impact report from the production space's configuration, for one purpose: in Markdown and in JSON, with its SHA-256. The report is stable: the same configuration gives the same document and the same hash. The controller approves it by link, as `ripd` with the purpose as subject, and `approved_at` says when it approved this very document, by its hash; a configuration that changed since comes back without `approved_at`.

## Access review

Every 90 days, the controller confirms that the operators' access stays as it is. [`GET /v1/projects/{project_id}/access-review`](/en/api/control/access-review) says when it last approved, when the next review is due and whether a request is pending; the control plane asks for the review by itself when it falls due. `due_at` is null in a project with no controller apart from the tenant.

## Emergency access

An incident at three in the morning does not wait for a link. [`POST /v1/projects/{project_id}/emergency-access`](/en/api/control/emergency-access) gives the caller a role (`security`, `integration`, `review` or `analysis`) on one space of the project, at once, for at most four hours, with a required reason. The person's next token already carries the role. The controller is told by e-mail and can end the access by the link; the access is recorded as an approval of kind `emergency_access`, with the reason, and as a receipt in the spaces.

## Who pays

[`PUT /v1/projects/{project_id}/payer`](/en/api/control/payer) names the tenant that pays for the project when it is not the one that operates it; null returns to the operating tenant. It is a Niadra operations route, under contract, and `payer_tenant_id` shows in the project's read.

## Receipts and privacy

Every approval decision, every emergency access and every transfer enters the [receipt chain](/en/concepts/receipts) of the project's spaces, and the controller can audit them through its own chain. The DPO e-mail never leaves its seal; the company's registry number never leaves in clear; a link's token never appears in an API URL or a log.

## Next steps

<CardGroup cols={2}>
  <Card title="Operating a controller's project" href="/en/guides/controller-approvals">
    the walkthrough, from the legal entities to the first approval.
  </Card>

  <Card title="Console access" href="/en/concepts/console-access">
    roles, the second factor and SSO.
  </Card>

  <Card title="Privacy, erasure and export" href="/en/concepts/privacy">
    purposes, policy and retention, what the controller approves.
  </Card>

  <Card title="Request an approval" href="/en/api/control/approvals-create">
    the reference of `POST /v1/approvals`.
  </Card>
</CardGroup>
