# Change the Institution Callback Settings

> Coming soon, upon request — this feature is turned on for your tenant by the Aurea team. [Contact us](https://www.aureahub.com/contact)

Save one environment's callback: its mode, your endpoint, your answer keys, the fallback, the RETRY window and the approval requests.

## Overview

- **What the body leaves out keeps its stored value** — the first time, its default: `off`, `reject`, 48 hours, 60 seconds, approvals `off`. `mode` is in every save; `publicKeys`, when sent, replaces the list; `"url": null` removes the endpoint.
- `201` when the environment had no settings, `200` otherwise: `{ "settings", "created" }`, the settings as [Get the Settings](https://docs.aureahub.com/docs/institution-callback-get.md) shows them. `version` goes up by one at every save.
- `mode` `on` needs `url`, one or two `publicKeys`, and Aurea's request key in place (`409` `INSTITUTION_CALLBACK_SIGNER_NOT_CONFIGURED`). `approvals.mode` `on` needs `approvals.approverUserId`. Every rule: [Institution Callback › The Settings](https://docs.aureahub.com/docs/guide-institution-callback.md).
- Your endpoint is asked only once your tenant has institution callbacks [Coming soon, upon request](https://docs.aureahub.com/docs/feature-availability.md). Check it first with [Send a Test](https://docs.aureahub.com/docs/institution-callback-test.md).
- The body is checked as sent: a field that doesn't belong, or a value of the wrong type, is refused rather than ignored or converted. A change your tenant's quorum holds is checked when it runs: a body the API refuses ends its request `failed` with that refusal.
- For `owner`, `tenantadmin`, `non_signing_admin` and `security_admin`, on their own tenant. Each save is written to your [audit trail](https://docs.aureahub.com/docs/audit-events.md) [Coming soon, upon request](https://docs.aureahub.com/docs/feature-availability.md), as `institution_callback.settings_changed`: the names of the fields changed, never their values.

> Note: **Your tenant's quorum** [Coming soon, upon request](https://docs.aureahub.com/docs/feature-availability.md) — where it holds administrators' actions (a tenant on the institutional security profile by its profile; every other tenant's records them only): this call answers `202` `{ "state": "awaiting_quorum", "requestId" }` — the **202** tab below — and nothing is done until another administrator of your tenant approves it; the answer it would have given is then read once by who asked ([Read the Answer](https://docs.aureahub.com/docs/quorum-request-result.md)). With no other administrator able to approve it, it is done at once. [Your Tenant's Quorum](https://docs.aureahub.com/docs/guide-tenant-quorum.md). Every other tenant gets the answers below, unchanged.

## Endpoint

### `PUT /v1/admin/tenants/{id}/institution-callback/{environment}`

Authentication: bearer token required.

Saves one environment's callback settings (201 the first time, 200 after).

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | Tenant UUID |
| `environment` | string | yes | `production` (main networks) or `sandbox` (test networks) |

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `mode` | string | yes | `off` or `on` |
| `url` | string \| null | no | Your endpoint: https, a public host, up to 2048 characters; `null` removes it |
| `publicKeys` | object[] | no | One or two P-256 public keys as JWKs: `kty`, `crv`, `x`, `y` |
| `fallback` | string | no | `reject` (default) or `allow`: when your endpoint gives no usable answer |
| `retry.maxSeconds` | integer | no | 60–172800 (default 172800): how long a RETRY is asked again |
| `retry.intervalSeconds` | integer | no | 10–3600 (default 60): how often at least |
| `approvals.mode` | string | no | `off` or `on`; required when `approvals` is sent |
| `approvals.approverUserId` | string (uuid) \| null | no | The approver your endpoint answers for; required with `approvals.mode` `on` |

**Responses**

`201` Saved first

```json
{
  "settings": {
    "environment": "sandbox",
    "mode": "on",
    "url": "https://callback.example.com/aurea",
    "publicKeys": [
      {
        "kty": "EC",
        "crv": "P-256",
        "x": "5UHN8QYz8fLoGG81Tz-RFxcoaVCaSbbcoPZW6yzGzPc",
        "y": "bl4qqX2I3FUE6iUtK-6C_5-ebJ9F51oDHjN0Pvtqn54",
        "kid": "Cenbim1mvDgvFI0QH5-cJ5VDSCnXKkrqQ7IsgOxDYKQ"
      }
    ],
    "fallback": "reject",
    "effectiveFallback": "reject",
    "retry": { "maxSeconds": 172800, "intervalSeconds": 60 },
    "approvals": { "mode": "off", "approverUserId": null },
    "version": 1,
    "updatedAt": "2026-10-14T08:50:03.120Z"
  },
  "created": true
}
```

`202` Awaiting quorum

```json
{
  "state": "awaiting_quorum",
  "requestId": "4e2b9c17-8a3d-4f60-b5e1-7c9d0a2f6b38"
}
```

`200` Rotation

```json
{
  "settings": {
    "environment": "sandbox",
    "mode": "on",
    "url": "https://callback.example.com/aurea",
    "publicKeys": [
      {
        "kty": "EC",
        "crv": "P-256",
        "x": "5UHN8QYz8fLoGG81Tz-RFxcoaVCaSbbcoPZW6yzGzPc",
        "y": "bl4qqX2I3FUE6iUtK-6C_5-ebJ9F51oDHjN0Pvtqn54",
        "kid": "Cenbim1mvDgvFI0QH5-cJ5VDSCnXKkrqQ7IsgOxDYKQ"
      },
      {
        "kty": "EC",
        "crv": "P-256",
        "x": "ZQTI6CDkwT2S36ra20NscrUOvz7Zy_KoE_VyYq0tz4A",
        "y": "7nVIwFYpzjHboU6RTbjQgvx363Z-E8FgBbDrk1sTvb8",
        "kid": "re4KhLxDHSP-7ZaVV9MjPZSmIpaHH6o1Xly5KdPSf4Y"
      }
    ],
    "fallback": "reject",
    "effectiveFallback": "reject",
    "retry": { "maxSeconds": 172800, "intervalSeconds": 60 },
    "approvals": { "mode": "off", "approverUserId": null },
    "version": 2,
    "updatedAt": "2026-10-14T08:55:12.418Z"
  },
  "created": false
}
```

`400` Refused

```json
{
  "statusCode": 400,
  "error": "BadRequestError",
  "message": "url must be https",
  "details": { "code": "INSTITUTION_CALLBACK_INVALID", "field": "url" }
}
```

`409` No request key

```json
{
  "statusCode": 409,
  "error": "ConflictError",
  "message": "Aurea has no key to sign callback requests yet: the callback cannot be switched on",
  "details": { "code": "INSTITUTION_CALLBACK_SIGNER_NOT_CONFIGURED" }
}
```

**Example request**

```bash
curl -X PUT "https://api.aureahub.com/v1/admin/tenants/6f1e2d3c-4b5a-4968-8776-a5b4c3d2e1f0/institution-callback/sandbox" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "on",
    "url": "https://callback.example.com/aurea",
    "publicKeys": [{ "kty": "EC", "crv": "P-256", "x": "5UHN8QYz8fLoGG81Tz-RFxcoaVCaSbbcoPZW6yzGzPc", "y": "bl4qqX2I3FUE6iUtK-6C_5-ebJ9F51oDHjN0Pvtqn54" }],
    "fallback": "reject",
    "retry": { "maxSeconds": 172800, "intervalSeconds": 60 }
  }'
```

## Refusals

Nothing is saved. `400` `INSTITUTION_CALLBACK_INVALID`, with the field at fault in `details.field`:

- A body that does not fit — a missing `mode`, a field that doesn't belong, a value of the wrong type or out of range, three keys —: `The callback settings are not valid`.
- `url`: `url must be an absolute https URL`, `url must be https`, `url must not carry credentials`, `url must not carry a fragment`, `url must be a public host`; `url is required to switch the callback on`.
- `publicKeys`: `publicKeys needs one key at least to switch the callback on`, `publicKeys lists the same key twice`; one key (`publicKeys.0`, `publicKeys.1`): `publicKeys.0 must be a P-256 public key as a JWK:` and why — for example `crv must be "P-256"`, `x must be 32 bytes in unpadded base64url`, `the point is not on the curve` — or `publicKeys.0 carries a private key ("d"): send the public key only, and do not use this key pair`.
- `approvals.approverUserId`: `approvals.approverUserId is required to send the approvals`, `approvals.approverUserId must be an active approver of the tenant`.
- `environment` or `id`: `environment is not valid`, `id is not valid`.

`409` `INSTITUTION_CALLBACK_SIGNER_NOT_CONFIGURED` — `mode` `on` before Aurea's request key is in place. `404` `Tenant not found`.

---

Web version: https://docs.aureahub.com/#institution-callback-put
