---
title: "common.config-change@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/common.config-change"
updated: null
---

# common.config-change@1 · OpenVibe.Services

HTML: [common.config-change@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/common.config-change)

# ConfigChange `common.config-change@1`

Generated at 2026-11-13 06:25:48 UTC from [`openvibe-contracts v0.419.0`](https://github.com/OpenVibers/OpenVibe.Contracts/tree/v0.419.0) and [`openvibe-sdk v0.161.0`](https://github.com/OpenVibers/OpenVibe.SDK/tree/v0.161.0).

- Version: 1.0.0
- Owner: network
- Visibility: internal
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/common/config-change.v1.json`](/docs/contracts/common.config-change.json)

common.config-change@1 (AI Exchange D11): body of POST /internal/config/:namespace on a service's openvibe-shared/config admin routes. It proposes a new revision of the namespace and activates it (the store validates against the namespace schema, applies env pins and calls onActivate). \`merge: true\` starts from the active values; otherwise \`values\` is the whole new set. \`unset\` removes keys. A secret-class key's value is never sent here: it is 422 config.secret\_write\_only; use common.config-secret-put@1.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `values` | object | yes | The new values, one member per key. The store validates them against the namespace schema; a secret-class value here is refused. |  |
| `reason` | string | yes | Why the change is made; it is the revision's reason in the history. | - `minLength 1`<br>- `maxLength 500` |
| `merge` | boolean |  | Merge into the active values instead of replacing them. | - `default false` |
| `unset` | array of string |  | Keys to remove from the new revision. | - `maxItems 256`<br>- `unique items`<br>- `items: pattern ^[A-Za-z0-9_][A-Za-z0-9_.:-]{0,127}$` |

## Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

 Valid: merge-change

~~~~
{
  "values": {
    "max_bitrate_kbps": 7000,
    "youtube_api_key": {
      "redacted": true,
      "fingerprint": "c61d1b1293d59c54c56624f6d6161b8af976449db60f230ed977dcf3ba4bd31b"
    }
  },
  "reason": "Raise the bitrate cap for the tournament",
  "merge": true,
  "unset": [
    "legacy_banner"
  ]
}
~~~~

Valid: replace

~~~~
{
  "values": {
    "site_name": "OpenVibe.Live"
  },
  "reason": "Set the site name"
}
~~~~

Rejected: missing-reason

~~~~
{
  "values": {
    "site_name": "OpenVibe.Live"
  }
}
~~~~

Rejected: unknown-field

~~~~
{
  "values": {
    "site_name": "OpenVibe.Live"
  },
  "reason": "Set the site name",
  "actor": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  }
}
~~~~

Rejected: unset-not-a-list

~~~~
{
  "values": {
    "site_name": "OpenVibe.Live"
  },
  "reason": "Remove the old banner",
  "unset": "legacy_banner"
}
~~~~

## Validate

~~~~
const contracts = require('openvibe-contracts');
contracts.validate('common.config-change@1', value);   // { valid, errors: [{ path, message }] }
~~~~
