---
title: Integrations
description: Read the configurations an organization saved for your installed app, connect them, and report whether each one works.
---

Every installed connector uses the integrations API. It is how your app learns what an organization configured for it, and how it says whether that configuration works. Your app reads its configurations here, with their secrets. It then reports each configuration `ready` or `failed`.

Hydda One starts to use your app only after it reports a configuration `ready`. The [billing](/guides/surfaces/billing) queues and [signing](/guides/surfaces/signing) sends wait for that report.

## How an app is set up

Three things connect your app to an organization.

- **The manifest** is your app's description. It names the parts of Hydda One the app fills, such as `billing.invoicing` or `crm.signing`. It names the roles the app needs, and the configuration fields at each level. It can also name a `setupAddress`.
- **The installation** is your app inside one organization. Only an administrator of the organization installs it, and consents to the roles the manifest requests.
- **A configuration** holds the values and secrets an administrator saved for your installation. It belongs to one operational context: the organization itself (`level` `organization`) or one business (`level` `business_context`).

Saving a configuration grants your installation the role that part of Hydda One needs, at that context. A configuration at a level your manifest fills nothing at grants no role. An invoicing connector, for example, keeps each company's ERP credentials in a configuration at that business.

## What the token needs

The caller is the installation itself, with its own token. See [Authentication](/guides/authentication). No role is needed.

Two kinds of token are accepted:

- An installed connector's token from the installation-token grant.
- The token of an organization's own Application that the organization installed as an app.

The installation must be active. A disabled installation, or a token that matches no installation, answers `403`. A request without a token answers `401`.

## The flow

An app with a `setupAddress` connects each configuration on its own page. Use this when you need an OAuth consent, or when you collect secrets yourself.

```mermaid
sequenceDiagram
  actor Admin as Administrator
  participant H as Hydda One
  participant App as Your app
  Admin->>H: saves the configuration
  Admin->>H: starts the connection
  H-->>Admin: redirect to your setupAddress
  Admin->>App: opens the setup address
  App->>H: POST /v1/integrations/connection-references/redeem
  H-->>App: configurationId, operationalContextId and level
  App->>H: GET /v1/integrations/configurations
  H-->>App: values and secrets
  App->>Admin: consent or your own form
  App->>H: POST /v1/integrations/configurations/{configurationId}/ready
  App-->>Admin: redirect to return_url
```

Each call is described in the [integrations reference](/reference/integrations).

1. **Receive the administrator.** The browser arrives at your `setupAddress` with three query parameters: `reference`, `installation_id` and `return_url`.
2. **Get a token for the installation.** Use `installation_id` to request a token for that installation. Do not trust the id alone. The redeem in the next step proves it, because a token for another installation redeems nothing.
3. **Redeem the reference.** Call `POST /v1/integrations/connection-references/redeem` with `reference`. The answer names the `configurationId` the administrator is connecting, its `operationalContextId` and its `level`.
4. **Read the configuration.** Call `GET /v1/integrations/configurations` and find the configuration by its `id`.
5. **Connect it.** Complete the consent, or collect the secrets on your page. Check that the configuration works, for example with a test call to the external system.
6. **Report the result.** Call `POST /v1/integrations/configurations/{configurationId}/ready`. If the configuration cannot work, call `.../failed` with a `code` and a `reason`.
7. **Send the administrator back.** Redirect the browser to `return_url`.

An app without a `setupAddress` skips steps 1 to 3 and step 7. It reads its configurations when it starts. It checks each one and reports `ready` or `failed`.

### What a configuration carries

| Field | What it is |
| --- | --- |
| `id` | The configuration id. The status reports take it as `configurationId`. |
| `operationalContextId` | The organization or business the configuration applies to. |
| `level` | `organization` or `business_context`. |
| `values` | The fields the administrator filled in. |
| `secrets` | The secrets, in plain text, keyed by field. |
| `status` | `pending`, `ready` or `failed`. |
| `manifestVersion` | The version of your manifest the configuration was saved against. |
| `updatedAt` | When the configuration last changed. |

A business configuration can leave a field empty when the organization configuration has a field with the same key and type. Hydda One then fills it from the organization configuration before it answers. A value saved at the business wins. Your app never merges values itself.

## Configuration statuses

| `status` | Meaning |
| --- | --- |
| `pending` | Your app has not reported on this version of the configuration. |
| `ready` | Your app reported that the configuration works. |
| `failed` | Your app reported that it cannot use the configuration. The administrator sees your `code` and `reason`. |

You can report `failed` on a `ready` configuration, for example when a credential stops working. You can report `ready` on a `failed` one once it works again.

When an administrator changes a configuration, its status returns to `pending` and `updatedAt` changes. Check the new values and report again.

## Rules for callers

### Reports are safe to repeat

Reporting `ready` again changes nothing. Reporting `failed` again with the same `code` and `reason` also changes nothing. Both answer `204`.

### Keep secrets secret

The configurations list is the only place Hydda One returns secrets, and only to the installation they belong to. Never log them. Never put one in a failure `reason`, because the administrator reads it.

### Connection references

A reference works once, within ten minutes, and only for the installation it was made for. If the administrator starts a new connection, the earlier reference stops working.

Every refused reference gets the same answer: `400` with `INTEGRATIONS_CONNECTION_REFERENCE_INVALID`. The answer does not say whether the reference was unknown, expired, used, replaced or another installation's. A refused redeem does not count as the one use.

An administrator who returns before you report sees the configuration as `pending`. Report as soon as you know the result.

### Limits

| What | Limit |
| --- | --- |
| `code` on failed | Lower snake case, such as `invalid_api_key`. 1 to 100 characters. |
| `reason` on failed | 1 to 500 characters. |
| `reference` on redeem | 1 to 200 characters. |
| Requests under `/v1/integrations` | 60 a minute from each IP address. |

Read your configurations when your app starts and after each redeem, not before every call. A request over the rate limit gets `429`.

## Errors to handle

| Code | Status | When |
| --- | --- | --- |
| `INTEGRATIONS_CONNECTION_REFERENCE_INVALID` | 400 | The reference cannot be redeemed. A new reference comes only when an administrator starts the connection again. |
| `INTEGRATIONS_CONFIGURATION_NOT_FOUND` | 404 | The `configurationId` is not one of your installation's configurations. |
| `VALIDATION_FAILED` | 400 | A body or path parameter does not match its schema. |

[Errors](/guides/errors) lists every integrations code and its status.
