---
title: "watch.rate.changed@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/watch.rate.changed"
updated: null
---

# watch.rate.changed@1 · OpenVibe.Services

HTML: [watch.rate.changed@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/watch.rate.changed)

# WatchRateChangedPayload `watch.rate.changed@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: watch
- Visibility: first-party
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/events/payloads/watch.rate.changed.v1.json`](/docs/contracts/watch.rate.changed.json)

watch.rate.changed v1 (OpenVibe.Watch server/provider-rates.js changeEvent(); plan P6, flag WATCH\_PROVIDER\_RATES off by default): a provider's published price document stated a different value for one model and token class than Watch last observed. It is EVIDENCE, not a rate card: Watch writes no billable price, and a person (never a service or an agent) must approve or reject the change; the decision is dated evidence for OpenVibe.AI's catalog operator. Money is integer nano-USD per million tokens as a decimal string (D1: never a float). Envelope: subject { type: provider-rate, id: <source\_key> }, visibility internal, priority important, source and actor service:watch.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `change_id` | string | yes |  | - `pattern ^prc_[0-9A-HJKMNP-TV-Z]{26}$` |
| `source_key` | string | yes | The source Watch fetched: the provider's key in its registry (deepinfra, featherless). |  |
| `provider` | string | yes | The provider whose document stated the rate (deepinfra, featherless). |  |
| `model` | string | yes | The model id exactly as the provider's document stated it. |  |
| `token_class` | enum | yes | The D1 token classes. | - `one of "input", "cached_read", "cache_write", "output"` |
| `from_nano_usd_per_m` | string \| null | yes | The value Watch last observed, as an integer nano-USD per million tokens string; null for a first price. | - `pattern ^[0-9]{1,19}$` |
| `to_nano_usd_per_m` | string | yes | The value the document states now, as an integer nano-USD per million tokens string. | - `pattern ^[0-9]{1,19}$` |
| `currency` | string | yes | The document's currency; USD for both sources today. |  |
| `region` | string | yes | The document's scope; global for both sources today. |  |
| `effective_date` | string | yes | The first day this value was observed (YYYY-MM-DD); an unchanged value keeps its first date. | - `format date` |
| `source_url` | string | yes | The official document fetched; never a private or authenticated URL. | - `format uri` |
| `fetched_at` | string | yes |  | - `format date-time` |
| `approval_required` | boolean | yes | true for a change: it waits for a person's decision. |  |

## Examples

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

 Valid: deepinfra-input

~~~~
{
  "change_id": "prc_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "source_key": "deepinfra",
  "provider": "deepinfra",
  "model": "Qwen/Qwen3-Coder-30B-A3B-Instruct",
  "token_class": "input",
  "from_nano_usd_per_m": "70000000",
  "to_nano_usd_per_m": "90000000",
  "currency": "USD",
  "region": "global",
  "effective_date": "2026-11-03",
  "source_url": "https://api.deepinfra.com/models/list",
  "fetched_at": "2026-11-03T09:15:00.000Z",
  "approval_required": true
}
~~~~

Valid: first-price

~~~~
{
  "change_id": "prc_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "source_key": "featherless",
  "provider": "featherless",
  "model": "Qwen/Qwen3-8B",
  "token_class": "cached_read",
  "from_nano_usd_per_m": null,
  "to_nano_usd_per_m": "50000000",
  "currency": "USD",
  "region": "global",
  "effective_date": "2026-11-03",
  "source_url": "https://api.featherless.ai/v1/models",
  "fetched_at": "2026-11-03T10:00:00.000Z",
  "approval_required": true
}
~~~~

Rejected: bad-token-class

~~~~
{
  "change_id": "prc_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "source_key": "deepinfra",
  "provider": "deepinfra",
  "model": "Qwen/Qwen3-Coder-30B-A3B-Instruct",
  "token_class": "token-class",
  "from_nano_usd_per_m": "70000000",
  "to_nano_usd_per_m": "90000000",
  "currency": "USD",
  "region": "global",
  "effective_date": "2026-11-03",
  "source_url": "https://api.deepinfra.com/models/list",
  "fetched_at": "2026-11-03T09:15:00.000Z",
  "approval_required": true
}
~~~~

Rejected: money-float

~~~~
{
  "change_id": "prc_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "source_key": "deepinfra",
  "provider": "deepinfra",
  "model": "Qwen/Qwen3-Coder-30B-A3B-Instruct",
  "token_class": "input",
  "from_nano_usd_per_m": "70000000",
  "to_nano_usd_per_m": "0.09",
  "currency": "USD",
  "region": "global",
  "effective_date": "2026-11-03",
  "source_url": "https://api.deepinfra.com/models/list",
  "fetched_at": "2026-11-03T09:15:00.000Z",
  "approval_required": true
}
~~~~

Rejected: money-number

~~~~
{
  "change_id": "prc_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "source_key": "deepinfra",
  "provider": "deepinfra",
  "model": "Qwen/Qwen3-Coder-30B-A3B-Instruct",
  "token_class": "input",
  "from_nano_usd_per_m": "70000000",
  "to_nano_usd_per_m": 90000000,
  "currency": "USD",
  "region": "global",
  "effective_date": "2026-11-03",
  "source_url": "https://api.deepinfra.com/models/list",
  "fetched_at": "2026-11-03T09:15:00.000Z",
  "approval_required": true
}
~~~~

## Validate

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