openvibers/openvibe.contracts Commits
0.287.0: billing.credit.settled event payload (AI Exchange D1/D9) (#296)
Changes
@@@ -1,6 +1,26 @@# Changelog++## 0.287.0 — 2026-11-04++++- **`billing.credit.settled@1`** (AI Exchange money, D1 and D9).++ - OpenVibe.Billing emits it from the settle transaction of a Credits hold (`server/ops/credits.js` `settleHold`);++ OpenVibe.Report consumes it for aggregate analytics.++ - It carries `settlement_id`, `hold_id`, the hold's `service`, `settled_at`, the answering attempt's++ `deployment_id` (`<provider>:<model>`, nullable) and `provider_access` (nullable), `rate_version`, the four++ `usage` token counts, `charge_nano_usd`, `supply_cost_nano_usd`, `shortfall_nano_usd`, `released_nano_usd`,++ `byok` and `sandbox`.++ - Deliberately no `subject`, no `project_id` and no account id: the event is for aggregates, while per-person++ statements are read from Billing.++ - Money is integer nano-USD as decimal strings (D1); a number amount and a subject field are invalid fixtures.++ - Billing's manifest lists the event in `eventsProduced`; Report's lists it in `eventsConsumed`.++- **`sandbox` on Credits holds: `billing.credit-hold@1` and `billing.credit-hold-create-request@1`** (D10, additive).++ - An optional boolean `sandbox` (default false) says the hold draws on that person's sandbox credit for the project++ (account kind `usd_credit_sandbox`, owner `subject:project`), never on real Credits; a real hold never draws on++ sandbox credit.++ - `billing.credit-sandbox-grant-request@1` now says its grants land in that sandbox account.++ - Valid fixtures cover `sandbox: true`; `sandbox: "yes"` is invalid.++## 0.286.0 — 2026-11-04- **Provider-rate evidence events: `watch.rate.changed@1`, `watch.rate.approved@1`, `watch.rate.rejected@1`**@@@ -2,7 +2,7 @@> Machine-readable contracts for the whole OpenVibe network.--**Status:** alpha (first released in Wave 1; the release is package.json's `version`, tagged). At v0.286.0: 974 schemas in `contracts/catalog.json`, 45 service manifests, 440 capability manifests, 13 namespace manifests and the staff capability map. Service repositories run `openvibe-contracts-check` and the pin-drift check in CI, and deployed services verify service and app tokens with `serviceAuth` in production. Consumers pin release tags (each repository's `STATUS.json` names its pin). `node scripts/docs-currency.js <root>` checks every checkout's README and `STATUS.json` against its code: the pins and versions they name, a library's consumer list, the deployed flag against the manifest, README links, and the paths and migrations they name. `node scripts/estate.js` generates `docs/ESTATE.md` and `manifests/repositories/` from the estate checkouts, and `--check` fails on drift (plan T1 step 3).++**Status:** alpha (first released in Wave 1; the release is package.json's `version`, tagged). At v0.287.0: 975 schemas in `contracts/catalog.json`, 45 service manifests, 440 capability manifests, 13 namespace manifests and the staff capability map. Service repositories run `openvibe-contracts-check` and the pin-drift check in CI, and deployed services verify service and app tokens with `serviceAuth` in production. Consumers pin release tags (each repository's `STATUS.json` names its pin). `node scripts/docs-currency.js <root>` checks every checkout's README and `STATUS.json` against its code: the pins and versions they name, a library's consumer list, the deployed flag against the manifest, README links, and the paths and migrations they name. `node scripts/estate.js` generates `docs/ESTATE.md` and `manifests/repositories/` from the estate checkouts, and `--check` fails on drift (plan T1 step 3).**Plan:** OpenVibe Development Roadmap, Wave 1 (implementation plan rev 3, §3.1 and §18.11).**License:** AGPL-3.0 (same as every OpenVibe service).@@@ -53,6 +53,11 @@"type": "string","pattern": "^[a-z][a-z0-9-]{0,39}$","description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."++ },++ "sandbox": {++ "type": "boolean",++ "default": false,++ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."}}}@@@ -81,6 +81,11 @@"type": "string","pattern": "^[a-z][a-z0-9-]{0,39}$","description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."++ },++ "sandbox": {++ "type": "boolean",++ "default": false,++ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."}}}@@@ -2,7 +2,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/billing/credit-sandbox-grant-request.v1.json","title": "BillingCreditSandboxGrantRequest",-- "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).",++ "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.","type": "object","required": ["subject",@@@ -2223,6 +2223,15 @@"status": "active","adr": "ADR-012"},++ {++ "id": "billing.credit.settled",++ "version": "1.0.0",++ "owner": "billing",++ "schema": "events/payloads/billing.credit.settled.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },{"id": "billing.admin-request","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1,97 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/billing.credit.settled.v1.json",++ "title": "BillingCreditSettledPayload",++ "description": "billing.credit.settled v1 (OpenVibe.Billing server/ops/credits.js settleHold(); written with the settlement row in the settle transaction): a Credits hold was settled once. It is AGGREGATE-ONLY on purpose: it carries no subject, no project_id and no account id, so a consumer can count services, routes and money but cannot reconstruct a person's statement; per-person statements are read from Billing's own ledger. OpenVibe.Report consumes it for aggregate analytics. Money is integer nano-USD as decimal strings (D1: never a float). Envelope: subject { type: credit-settlement, id: stl_… }, visibility internal, priority important, actor service:billing.",++ "type": "object",++ "additionalProperties": false,++ "required": ["settlement_id", "hold_id", "service", "settled_at", "deployment_id", "provider_access", "rate_version", "usage", "charge_nano_usd", "supply_cost_nano_usd", "shortfall_nano_usd", "released_nano_usd", "byok", "sandbox"],++ "properties": {++ "settlement_id": {++ "type": "string",++ "pattern": "^stl_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "ULID settlement id, the same one the settle result and Billing's statement use."++ },++ "hold_id": {++ "type": "string",++ "pattern": "^hld_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The settled hold."++ },++ "service": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{0,39}$",++ "description": "The hold's service (D9): which metered service spent the credit, e.g. ai. Read from the hold; the settle request does not carry it."++ },++ "settled_at": {++ "type": "string",++ "format": "date-time",++ "description": "When the settlement committed (the settlement row's created_at)."++ },++ "deployment_id": {++ "type": ["string", "null"],++ "maxLength": 256,++ "description": "The answering attempt's deployment id, '<provider>:<model>' as sent in the settle request's attempts[].deployment_id; null when no attempt answered (a cache hit or a BYOK call with no managed attempt)."++ },++ "provider_access": {++ "type": ["string", "null"],++ "enum": ["OWN_DEPLOYMENT", "AUTHORIZED_WHOLESALE", "CUSTOMER_BYOK", "RESTRICTED", "UNVERIFIED", null],++ "description": "The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one."++ },++ "rate_version": {++ "type": "string",++ "description": "The retail rate-card version the usage was priced against (the settle request's retail.version)."++ },++ "usage": {++ "type": "object",++ "description": "The measured token counts, the same shape as billing.credit-hold-settle-request@1's usage.",++ "required": ["input_tokens", "cached_read_tokens", "cache_write_tokens", "output_tokens"],++ "additionalProperties": false,++ "properties": {++ "input_tokens": {++ "type": "integer",++ "minimum": 0++ },++ "cached_read_tokens": {++ "type": "integer",++ "minimum": 0++ },++ "cache_write_tokens": {++ "type": "integer",++ "minimum": 0++ },++ "output_tokens": {++ "type": "integer",++ "minimum": 0++ }++ }++ },++ "charge_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "The charge the settlement recorded, integer nano-USD (D1). Usage beyond the hold and free balance is separately shortfall_nano_usd."++ },++ "supply_cost_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK."++ },++ "shortfall_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1)."++ },++ "released_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "Hold amount returned to the account, integer nano-USD (D1)."++ },++ "byok": {++ "type": "boolean",++ "description": "True when the caller supplied their own provider key; the retail charge is 0."++ },++ "sandbox": {++ "type": "boolean",++ "description": "True when the hold was funded from usd_credit_sandbox (BILLING_CREDITS_SANDBOX), never paid credit."++ }++ }++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "idempotency_key": "hold-key-sandbox-002",++ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "max_nano_usd": "50000000",++ "rate_version": "rr-2026-11-03-001",++ "request_fingerprint": "fp-chat-sandbox-002",++ "service": "ai",++ "sandbox": "yes"++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "idempotency_key": "hold-key-sandbox-001",++ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "max_nano_usd": "50000000",++ "rate_version": "rr-2026-11-03-001",++ "request_fingerprint": "fp-chat-sandbox-001",++ "service": "ai",++ "sandbox": true++}nnew file mode 100644@@@ -0,0 +1,15 @@++{++ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNP2",++ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "held_nano_usd": "100000000",++ "available_nano_usd": "50000000",++ "max_nano_usd": "100000000",++ "rate_version": "rr-2026-11-03-001",++ "request_fingerprint": "fp-chat-sandbox-002",++ "lease_expires_at": "2026-11-04T01:00:00.000Z",++ "status": "active",++ "created_at": "2026-11-04T00:00:00.000Z",++ "service": "ai",++ "sandbox": "yes"++}nnew file mode 100644@@@ -0,0 +1,15 @@++{++ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNP1",++ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },++ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "held_nano_usd": "100000000",++ "available_nano_usd": "50000000",++ "max_nano_usd": "100000000",++ "rate_version": "rr-2026-11-03-001",++ "request_fingerprint": "fp-chat-sandbox-001",++ "lease_expires_at": "2026-11-04T01:00:00.000Z",++ "status": "active",++ "created_at": "2026-11-04T00:00:00.000Z",++ "service": "ai",++ "sandbox": true++}nnew file mode 100644@@@ -0,0 +1,21 @@++{++ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "ai",++ "settled_at": "2026-11-04T12:00:05.000Z",++ "deployment_id": "deepinfra:Qwen/Qwen3-Coder-30B-A3B-Instruct",++ "provider_access": "AUTHORIZED_WHOLESALE",++ "rate_version": "rr-2026-11-03-001",++ "usage": {++ "input_tokens": 1000,++ "cached_read_tokens": 0,++ "cache_write_tokens": 0,++ "output_tokens": 500++ },++ "charge_nano_usd": 11,++ "supply_cost_nano_usd": "9",++ "shortfall_nano_usd": "0",++ "released_nano_usd": "9999989",++ "byok": false,++ "sandbox": false++}nnew file mode 100644@@@ -0,0 +1,25 @@++{++ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "ai",++ "settled_at": "2026-11-04T12:00:05.000Z",++ "deployment_id": "deepinfra:Qwen/Qwen3-Coder-30B-A3B-Instruct",++ "provider_access": "AUTHORIZED_WHOLESALE",++ "rate_version": "rr-2026-11-03-001",++ "usage": {++ "input_tokens": 1000,++ "cached_read_tokens": 0,++ "cache_write_tokens": 0,++ "output_tokens": 500++ },++ "charge_nano_usd": "11",++ "supply_cost_nano_usd": "9",++ "shortfall_nano_usd": "0",++ "released_nano_usd": "9999989",++ "byok": false,++ "sandbox": false,++ "subject": {++ "type": "user",++ "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"++ }++}nnew file mode 100644@@@ -0,0 +1,21 @@++{++ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNP1",++ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNP2",++ "service": "ai",++ "settled_at": "2026-11-04T12:00:07.000Z",++ "deployment_id": null,++ "provider_access": null,++ "rate_version": "rr-2026-11-03-001",++ "usage": {++ "input_tokens": 0,++ "cached_read_tokens": 0,++ "cache_write_tokens": 0,++ "output_tokens": 0++ },++ "charge_nano_usd": "0",++ "supply_cost_nano_usd": "0",++ "shortfall_nano_usd": "0",++ "released_nano_usd": "500000",++ "byok": true,++ "sandbox": true++}nnew file mode 100644@@@ -0,0 +1,21 @@++{++ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "ai",++ "settled_at": "2026-11-04T12:00:05.000Z",++ "deployment_id": "deepinfra:Qwen/Qwen3-Coder-30B-A3B-Instruct",++ "provider_access": "AUTHORIZED_WHOLESALE",++ "rate_version": "rr-2026-11-03-001",++ "usage": {++ "input_tokens": 1000,++ "cached_read_tokens": 0,++ "cache_write_tokens": 0,++ "output_tokens": 500++ },++ "charge_nano_usd": "11",++ "supply_cost_nano_usd": "9",++ "shortfall_nano_usd": "0",++ "released_nano_usd": "9999989",++ "byok": false,++ "sandbox": false++}@@@ -25315,6 +25315,141 @@}}},++ "billing.credit.settled": {++ "version": "1.0.0",++ "owner": "billing",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/billing.credit.settled.v1.json",++ "title": "BillingCreditSettledPayload",++ "description": "billing.credit.settled v1 (OpenVibe.Billing server/ops/credits.js settleHold(); written with the settlement row in the settle transaction): a Credits hold was settled once. It is AGGREGATE-ONLY on purpose: it carries no subject, no project_id and no account id, so a consumer can count services, routes and money but cannot reconstruct a person's statement; per-person statements are read from Billing's own ledger. OpenVibe.Report consumes it for aggregate analytics. Money is integer nano-USD as decimal strings (D1: never a float). Envelope: subject { type: credit-settlement, id: stl_… }, visibility internal, priority important, actor service:billing.",++ "type": "object",++ "additionalProperties": false,++ "required": [++ "settlement_id",++ "hold_id",++ "service",++ "settled_at",++ "deployment_id",++ "provider_access",++ "rate_version",++ "usage",++ "charge_nano_usd",++ "supply_cost_nano_usd",++ "shortfall_nano_usd",++ "released_nano_usd",++ "byok",++ "sandbox"++ ],++ "properties": {++ "settlement_id": {++ "type": "string",++ "pattern": "^stl_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "ULID settlement id, the same one the settle result and Billing's statement use."++ },++ "hold_id": {++ "type": "string",++ "pattern": "^hld_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The settled hold."++ },++ "service": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{0,39}$",++ "description": "The hold's service (D9): which metered service spent the credit, e.g. ai. Read from the hold; the settle request does not carry it."++ },++ "settled_at": {++ "type": "string",++ "format": "date-time",++ "description": "When the settlement committed (the settlement row's created_at)."++ },++ "deployment_id": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 256,++ "description": "The answering attempt's deployment id, '<provider>:<model>' as sent in the settle request's attempts[].deployment_id; null when no attempt answered (a cache hit or a BYOK call with no managed attempt)."++ },++ "provider_access": {++ "type": [++ "string",++ "null"++ ],++ "enum": [++ "OWN_DEPLOYMENT",++ "AUTHORIZED_WHOLESALE",++ "CUSTOMER_BYOK",++ "RESTRICTED",++ "UNVERIFIED",++ null++ ],++ "description": "The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one."++ },++ "rate_version": {++ "type": "string",++ "description": "The retail rate-card version the usage was priced against (the settle request's retail.version)."++ },++ "usage": {++ "type": "object",++ "description": "The measured token counts, the same shape as billing.credit-hold-settle-request@1's usage.",++ "required": [++ "input_tokens",++ "cached_read_tokens",++ "cache_write_tokens",++ "output_tokens"++ ],++ "additionalProperties": false,++ "properties": {++ "input_tokens": {++ "type": "integer",++ "minimum": 0++ },++ "cached_read_tokens": {++ "type": "integer",++ "minimum": 0++ },++ "cache_write_tokens": {++ "type": "integer",++ "minimum": 0++ },++ "output_tokens": {++ "type": "integer",++ "minimum": 0++ }++ }++ },++ "charge_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "The charge the settlement recorded, integer nano-USD (D1). Usage beyond the hold and free balance is separately shortfall_nano_usd."++ },++ "supply_cost_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK."++ },++ "shortfall_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1)."++ },++ "released_nano_usd": {++ "type": "string",++ "pattern": "^[0-9]{1,19}$",++ "description": "Hold amount returned to the account, integer nano-USD (D1)."++ },++ "byok": {++ "type": "boolean",++ "description": "True when the caller supplied their own provider key; the retail charge is 0."++ },++ "sandbox": {++ "type": "boolean",++ "description": "True when the hold was funded from usd_credit_sandbox (BILLING_CREDITS_SANDBOX), never paid credit."++ }++ }++ }++ },"billing.admin-request": {"version": "1.0.0","owner": "billing",@@@ -27454,6 +27589,11 @@"type": "string","pattern": "^[a-z][a-z0-9-]{0,39}$","description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."++ },++ "sandbox": {++ "type": "boolean",++ "default": false,++ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."}}}@@@ -27705,6 +27845,11 @@"type": "string","pattern": "^[a-z][a-z0-9-]{0,39}$","description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."++ },++ "sandbox": {++ "type": "boolean",++ "default": false,++ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."}}}@@@ -100477,7 +100622,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/billing/credit-sandbox-grant-request.v1.json","title": "BillingCreditSandboxGrantRequest",-- "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).",++ "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.","type": "object","required": ["subject",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Actor API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bench API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3104,6 +3104,11 @@"type": "string","pattern": "^[a-z][a-z0-9-]{0,39}$","description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."++ },++ "sandbox": {++ "type": "boolean",++ "default": false,++ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."}}},@@@ -3369,7 +3374,7 @@},"billing.credit-sandbox-grant-request.v1": {"title": "BillingCreditSandboxGrantRequest",-- "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).",++ "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.","type": "object","required": ["subject",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Blog API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bot API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Chat API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Codes API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Community API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Coupons API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Deals API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Domains API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Events API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Food API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Games API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Host API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Inventory API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.MediaHub API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Media API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Network API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.News API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenRestream API",-- "version": "0.286.0",-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Play API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Quest API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Report API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Reviews API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Run API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Search API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Services API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Sources API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Space API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tips API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Today API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tools API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Trade API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.VIP API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Vision API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Watch API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Wiki API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Work API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Zone API",-- "version": "0.286.0",-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.287.0",++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -163890,6 +163890,74 @@ export interface BillingReceiptExternalPayload {};}++/** [email protected] (owner: billing) */++/**++ * billing.credit.settled v1 (OpenVibe.Billing server/ops/credits.js settleHold(); written with the settlement row in the settle transaction): a Credits hold was settled once. It is AGGREGATE-ONLY on purpose: it carries no subject, no project_id and no account id, so a consumer can count services, routes and money but cannot reconstruct a person's statement; per-person statements are read from Billing's own ledger. OpenVibe.Report consumes it for aggregate analytics. Money is integer nano-USD as decimal strings (D1: never a float). Envelope: subject { type: credit-settlement, id: stl_… }, visibility internal, priority important, actor service:billing.++ */++export interface BillingCreditSettledPayload {++ /**++ * ULID settlement id, the same one the settle result and Billing's statement use.++ */++ settlement_id: string;++ /**++ * The settled hold.++ */++ hold_id: string;++ /**++ * The hold's service (D9): which metered service spent the credit, e.g. ai. Read from the hold; the settle request does not carry it.++ */++ service: string;++ /**++ * When the settlement committed (the settlement row's created_at).++ */++ settled_at: string;++ /**++ * The answering attempt's deployment id, '<provider>:<model>' as sent in the settle request's attempts[].deployment_id; null when no attempt answered (a cache hit or a BYOK call with no managed attempt).++ */++ deployment_id: string | null;++ /**++ * The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one.++ */++ provider_access: "OWN_DEPLOYMENT" | "AUTHORIZED_WHOLESALE" | "CUSTOMER_BYOK" | "RESTRICTED" | "UNVERIFIED" | null;++ /**++ * The retail rate-card version the usage was priced against (the settle request's retail.version).++ */++ rate_version: string;++ /**++ * The measured token counts, the same shape as billing.credit-hold-settle-request@1's usage.++ */++ usage: {++ input_tokens: number;++ cached_read_tokens: number;++ cache_write_tokens: number;++ output_tokens: number;++ };++ /**++ * The charge the settlement recorded, integer nano-USD (D1). Usage beyond the hold and free balance is separately shortfall_nano_usd.++ */++ charge_nano_usd: string;++ /**++ * What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK.++ */++ supply_cost_nano_usd: string;++ /**++ * Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1).++ */++ shortfall_nano_usd: string;++ /**++ * Hold amount returned to the account, integer nano-USD (D1).++ */++ released_nano_usd: string;++ /**++ * True when the caller supplied their own provider key; the retail charge is 0.++ */++ byok: boolean;++ /**++ * True when the hold was funded from usd_credit_sandbox (BILLING_CREDITS_SANDBOX), never paid credit.++ */++ sandbox: boolean;++}++/** [email protected] (owner: billing) *//*** billing.admin-request@1: bodies of billing.ledger.admin on OpenVibe.Billing (operators). POST /api/v1/admin/freeze: { on, reason? } (unfreezing processes the provider deliveries stored meanwhile; allowed while frozen). POST /api/v1/admin/adjustments: { from, to, amount, reason, relates_to? } moves value between two accounts of one currency. POST /api/v1/purchases/settle: { provider, provider_ref, subject?, amount_cents, bits, intent_id?, test? } books a provider receipt. POST /api/v1/admin/provider-events/:id/reprocess, POST /api/v1/admin/sweep and the GETs (freeze, reconcile, provider-events, import-holds) take no body. Adjustments and settlements need an Idempotency-Key and are refused while frozen.@@@ -164631,6 +164699,10 @@ export interface BillingCreditHold {* Which metered service spends the credit (D9): ai, run, ... Defaults to ai.*/service?: string;++ /**++ * D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false.++ */++ sandbox?: boolean;}/** [email protected] (owner: billing) */@@@ -164723,6 +164795,10 @@ export interface BillingCreditHoldCreateRequest {* Which metered service spends the credit (D9): ai, run, ... Defaults to ai.*/service?: string;++ /**++ * D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false.++ */++ sandbox?: boolean;}/** [email protected] (owner: billing) */@@@ -285250,7 +285326,7 @@ export interface TodayAgenda {/** [email protected] (owner: billing) *//**-- * billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).++ * billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.*/export interface BillingCreditSandboxGrantRequest {subject: SubjectRef;@@@ -46,7 +46,8 @@"billing.cashout.paid","billing.cashout.denied","billing.staff.action",-- "billing.receipt.external"++ "billing.receipt.external",++ "billing.credit.settled"],"eventsConsumed": [],"namespacesOwned": [@@@ -23,7 +23,8 @@"report.index_document.upserted"],"eventsConsumed": [-- "ai.call.recorded"++ "ai.call.recorded",++ "billing.credit.settled"],"namespacesOwned": ["report.*"@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.286.0",++ "version": "0.287.0","description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.","main": "index.js","types": "generated/typescript/index.d.ts",
@@ -1,6 +1,26 @@
@@ -1,6 +1,26 @@
# Changelog
# Changelog
+## 0.287.0 — 2026-11-04
+
+- **`billing.credit.settled@1`** (AI Exchange money, D1 and D9).
+ - OpenVibe.Billing emits it from the settle transaction of a Credits hold (`server/ops/credits.js` `settleHold`);
+ OpenVibe.Report consumes it for aggregate analytics.
+ - It carries `settlement_id`, `hold_id`, the hold's `service`, `settled_at`, the answering attempt's
+ `deployment_id` (`<provider>:<model>`, nullable) and `provider_access` (nullable), `rate_version`, the four
+ `usage` token counts, `charge_nano_usd`, `supply_cost_nano_usd`, `shortfall_nano_usd`, `released_nano_usd`,
+ `byok` and `sandbox`.
+ - Deliberately no `subject`, no `project_id` and no account id: the event is for aggregates, while per-person
+ statements are read from Billing.
+ - Money is integer nano-USD as decimal strings (D1); a number amount and a subject field are invalid fixtures.
+ - Billing's manifest lists the event in `eventsProduced`; Report's lists it in `eventsConsumed`.
+- **`sandbox` on Credits holds: `billing.credit-hold@1` and `billing.credit-hold-create-request@1`** (D10, additive).
+ - An optional boolean `sandbox` (default false) says the hold draws on that person's sandbox credit for the project
+ (account kind `usd_credit_sandbox`, owner `subject:project`), never on real Credits; a real hold never draws on
+ sandbox credit.
+ - `billing.credit-sandbox-grant-request@1` now says its grants land in that sandbox account.
+ - Valid fixtures cover `sandbox: true`; `sandbox: "yes"` is invalid.
+
## 0.286.0 — 2026-11-04
## 0.286.0 — 2026-11-04
- **Provider-rate evidence events: `watch.rate.changed@1`, `watch.rate.approved@1`, `watch.rate.rejected@1`**
- **Provider-rate evidence events: `watch.rate.changed@1`, `watch.rate.approved@1`, `watch.rate.rejected@1`**
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
> Machine-readable contracts for the whole OpenVibe network.
> Machine-readable contracts for the whole OpenVibe network.
-**Status:** alpha (first released in Wave 1; the release is package.json's `version`, tagged). At v0.286.0: 974 schemas in `contracts/catalog.json`, 45 service manifests, 440 capability manifests, 13 namespace manifests and the staff capability map. Service repositories run `openvibe-contracts-check` and the pin-drift check in CI, and deployed services verify service and app tokens with `serviceAuth` in production. Consumers pin release tags (each repository's `STATUS.json` names its pin). `node scripts/docs-currency.js <root>` checks every checkout's README and `STATUS.json` against its code: the pins and versions they name, a library's consumer list, the deployed flag against the manifest, README links, and the paths and migrations they name. `node scripts/estate.js` generates `docs/ESTATE.md` and `manifests/repositories/` from the estate checkouts, and `--check` fails on drift (plan T1 step 3).
+**Status:** alpha (first released in Wave 1; the release is package.json's `version`, tagged). At v0.287.0: 975 schemas in `contracts/catalog.json`, 45 service manifests, 440 capability manifests, 13 namespace manifests and the staff capability map. Service repositories run `openvibe-contracts-check` and the pin-drift check in CI, and deployed services verify service and app tokens with `serviceAuth` in production. Consumers pin release tags (each repository's `STATUS.json` names its pin). `node scripts/docs-currency.js <root>` checks every checkout's README and `STATUS.json` against its code: the pins and versions they name, a library's consumer list, the deployed flag against the manifest, README links, and the paths and migrations they name. `node scripts/estate.js` generates `docs/ESTATE.md` and `manifests/repositories/` from the estate checkouts, and `--check` fails on drift (plan T1 step 3).
**Plan:** OpenVibe Development Roadmap, Wave 1 (implementation plan rev 3, §3.1 and §18.11).
**Plan:** OpenVibe Development Roadmap, Wave 1 (implementation plan rev 3, §3.1 and §18.11).
**License:** AGPL-3.0 (same as every OpenVibe service).
**License:** AGPL-3.0 (same as every OpenVibe service).
@@ -53,6 +53,11 @@
@@ -53,6 +53,11 @@
"type": "string",
"type": "string",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
+ },
+ "sandbox": {
+ "type": "boolean",
+ "default": false,
+ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."
}
}
}
}
}
}
@@ -81,6 +81,11 @@
@@ -81,6 +81,11 @@
"type": "string",
"type": "string",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
+ },
+ "sandbox": {
+ "type": "boolean",
+ "default": false,
+ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."
}
}
}
}
}
}
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/billing/credit-sandbox-grant-request.v1.json",
"$id": "https://openvibe.network/contracts/billing/credit-sandbox-grant-request.v1.json",
"title": "BillingCreditSandboxGrantRequest",
"title": "BillingCreditSandboxGrantRequest",
- "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).",
+ "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.",
"type": "object",
"type": "object",
"required": [
"required": [
"subject",
"subject",
@@ -2223,6 +2223,15 @@
@@ -2223,6 +2223,15 @@
"status": "active",
"status": "active",
"adr": "ADR-012"
"adr": "ADR-012"
},
},
+ {
+ "id": "billing.credit.settled",
+ "version": "1.0.0",
+ "owner": "billing",
+ "schema": "events/payloads/billing.credit.settled.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
{
{
"id": "billing.admin-request",
"id": "billing.admin-request",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/billing.credit.settled.v1.json",
+ "title": "BillingCreditSettledPayload",
+ "description": "billing.credit.settled v1 (OpenVibe.Billing server/ops/credits.js settleHold(); written with the settlement row in the settle transaction): a Credits hold was settled once. It is AGGREGATE-ONLY on purpose: it carries no subject, no project_id and no account id, so a consumer can count services, routes and money but cannot reconstruct a person's statement; per-person statements are read from Billing's own ledger. OpenVibe.Report consumes it for aggregate analytics. Money is integer nano-USD as decimal strings (D1: never a float). Envelope: subject { type: credit-settlement, id: stl_… }, visibility internal, priority important, actor service:billing.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["settlement_id", "hold_id", "service", "settled_at", "deployment_id", "provider_access", "rate_version", "usage", "charge_nano_usd", "supply_cost_nano_usd", "shortfall_nano_usd", "released_nano_usd", "byok", "sandbox"],
+ "properties": {
+ "settlement_id": {
+ "type": "string",
+ "pattern": "^stl_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "ULID settlement id, the same one the settle result and Billing's statement use."
+ },
+ "hold_id": {
+ "type": "string",
+ "pattern": "^hld_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The settled hold."
+ },
+ "service": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{0,39}$",
+ "description": "The hold's service (D9): which metered service spent the credit, e.g. ai. Read from the hold; the settle request does not carry it."
+ },
+ "settled_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the settlement committed (the settlement row's created_at)."
+ },
+ "deployment_id": {
+ "type": ["string", "null"],
+ "maxLength": 256,
+ "description": "The answering attempt's deployment id, '<provider>:<model>' as sent in the settle request's attempts[].deployment_id; null when no attempt answered (a cache hit or a BYOK call with no managed attempt)."
+ },
+ "provider_access": {
+ "type": ["string", "null"],
+ "enum": ["OWN_DEPLOYMENT", "AUTHORIZED_WHOLESALE", "CUSTOMER_BYOK", "RESTRICTED", "UNVERIFIED", null],
+ "description": "The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one."
+ },
+ "rate_version": {
+ "type": "string",
+ "description": "The retail rate-card version the usage was priced against (the settle request's retail.version)."
+ },
+ "usage": {
+ "type": "object",
+ "description": "The measured token counts, the same shape as billing.credit-hold-settle-request@1's usage.",
+ "required": ["input_tokens", "cached_read_tokens", "cache_write_tokens", "output_tokens"],
+ "additionalProperties": false,
+ "properties": {
+ "input_tokens": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "cached_read_tokens": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "cache_write_tokens": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "output_tokens": {
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ },
+ "charge_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "The charge the settlement recorded, integer nano-USD (D1). Usage beyond the hold and free balance is separately shortfall_nano_usd."
+ },
+ "supply_cost_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK."
+ },
+ "shortfall_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1)."
+ },
+ "released_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "Hold amount returned to the account, integer nano-USD (D1)."
+ },
+ "byok": {
+ "type": "boolean",
+ "description": "True when the caller supplied their own provider key; the retail charge is 0."
+ },
+ "sandbox": {
+ "type": "boolean",
+ "description": "True when the hold was funded from usd_credit_sandbox (BILLING_CREDITS_SANDBOX), never paid credit."
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "idempotency_key": "hold-key-sandbox-002",
+ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "max_nano_usd": "50000000",
+ "rate_version": "rr-2026-11-03-001",
+ "request_fingerprint": "fp-chat-sandbox-002",
+ "service": "ai",
+ "sandbox": "yes"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "idempotency_key": "hold-key-sandbox-001",
+ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "max_nano_usd": "50000000",
+ "rate_version": "rr-2026-11-03-001",
+ "request_fingerprint": "fp-chat-sandbox-001",
+ "service": "ai",
+ "sandbox": true
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
+{
+ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNP2",
+ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "held_nano_usd": "100000000",
+ "available_nano_usd": "50000000",
+ "max_nano_usd": "100000000",
+ "rate_version": "rr-2026-11-03-001",
+ "request_fingerprint": "fp-chat-sandbox-002",
+ "lease_expires_at": "2026-11-04T01:00:00.000Z",
+ "status": "active",
+ "created_at": "2026-11-04T00:00:00.000Z",
+ "service": "ai",
+ "sandbox": "yes"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
+{
+ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNP1",
+ "subject": { "type": "app", "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ" },
+ "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "held_nano_usd": "100000000",
+ "available_nano_usd": "50000000",
+ "max_nano_usd": "100000000",
+ "rate_version": "rr-2026-11-03-001",
+ "request_fingerprint": "fp-chat-sandbox-001",
+ "lease_expires_at": "2026-11-04T01:00:00.000Z",
+ "status": "active",
+ "created_at": "2026-11-04T00:00:00.000Z",
+ "service": "ai",
+ "sandbox": true
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
+{
+ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "ai",
+ "settled_at": "2026-11-04T12:00:05.000Z",
+ "deployment_id": "deepinfra:Qwen/Qwen3-Coder-30B-A3B-Instruct",
+ "provider_access": "AUTHORIZED_WHOLESALE",
+ "rate_version": "rr-2026-11-03-001",
+ "usage": {
+ "input_tokens": 1000,
+ "cached_read_tokens": 0,
+ "cache_write_tokens": 0,
+ "output_tokens": 500
+ },
+ "charge_nano_usd": 11,
+ "supply_cost_nano_usd": "9",
+ "shortfall_nano_usd": "0",
+ "released_nano_usd": "9999989",
+ "byok": false,
+ "sandbox": false
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
+{
+ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "ai",
+ "settled_at": "2026-11-04T12:00:05.000Z",
+ "deployment_id": "deepinfra:Qwen/Qwen3-Coder-30B-A3B-Instruct",
+ "provider_access": "AUTHORIZED_WHOLESALE",
+ "rate_version": "rr-2026-11-03-001",
+ "usage": {
+ "input_tokens": 1000,
+ "cached_read_tokens": 0,
+ "cache_write_tokens": 0,
+ "output_tokens": 500
+ },
+ "charge_nano_usd": "11",
+ "supply_cost_nano_usd": "9",
+ "shortfall_nano_usd": "0",
+ "released_nano_usd": "9999989",
+ "byok": false,
+ "sandbox": false,
+ "subject": {
+ "type": "user",
+ "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
+{
+ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNP1",
+ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNP2",
+ "service": "ai",
+ "settled_at": "2026-11-04T12:00:07.000Z",
+ "deployment_id": null,
+ "provider_access": null,
+ "rate_version": "rr-2026-11-03-001",
+ "usage": {
+ "input_tokens": 0,
+ "cached_read_tokens": 0,
+ "cache_write_tokens": 0,
+ "output_tokens": 0
+ },
+ "charge_nano_usd": "0",
+ "supply_cost_nano_usd": "0",
+ "shortfall_nano_usd": "0",
+ "released_nano_usd": "500000",
+ "byok": true,
+ "sandbox": true
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
+{
+ "settlement_id": "stl_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "ai",
+ "settled_at": "2026-11-04T12:00:05.000Z",
+ "deployment_id": "deepinfra:Qwen/Qwen3-Coder-30B-A3B-Instruct",
+ "provider_access": "AUTHORIZED_WHOLESALE",
+ "rate_version": "rr-2026-11-03-001",
+ "usage": {
+ "input_tokens": 1000,
+ "cached_read_tokens": 0,
+ "cache_write_tokens": 0,
+ "output_tokens": 500
+ },
+ "charge_nano_usd": "11",
+ "supply_cost_nano_usd": "9",
+ "shortfall_nano_usd": "0",
+ "released_nano_usd": "9999989",
+ "byok": false,
+ "sandbox": false
+}
@@ -25315,6 +25315,141 @@
@@ -25315,6 +25315,141 @@
}
}
}
}
},
},
+ "billing.credit.settled": {
+ "version": "1.0.0",
+ "owner": "billing",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/billing.credit.settled.v1.json",
+ "title": "BillingCreditSettledPayload",
+ "description": "billing.credit.settled v1 (OpenVibe.Billing server/ops/credits.js settleHold(); written with the settlement row in the settle transaction): a Credits hold was settled once. It is AGGREGATE-ONLY on purpose: it carries no subject, no project_id and no account id, so a consumer can count services, routes and money but cannot reconstruct a person's statement; per-person statements are read from Billing's own ledger. OpenVibe.Report consumes it for aggregate analytics. Money is integer nano-USD as decimal strings (D1: never a float). Envelope: subject { type: credit-settlement, id: stl_… }, visibility internal, priority important, actor service:billing.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "settlement_id",
+ "hold_id",
+ "service",
+ "settled_at",
+ "deployment_id",
+ "provider_access",
+ "rate_version",
+ "usage",
+ "charge_nano_usd",
+ "supply_cost_nano_usd",
+ "shortfall_nano_usd",
+ "released_nano_usd",
+ "byok",
+ "sandbox"
+ ],
+ "properties": {
+ "settlement_id": {
+ "type": "string",
+ "pattern": "^stl_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "ULID settlement id, the same one the settle result and Billing's statement use."
+ },
+ "hold_id": {
+ "type": "string",
+ "pattern": "^hld_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The settled hold."
+ },
+ "service": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{0,39}$",
+ "description": "The hold's service (D9): which metered service spent the credit, e.g. ai. Read from the hold; the settle request does not carry it."
+ },
+ "settled_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the settlement committed (the settlement row's created_at)."
+ },
+ "deployment_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 256,
+ "description": "The answering attempt's deployment id, '<provider>:<model>' as sent in the settle request's attempts[].deployment_id; null when no attempt answered (a cache hit or a BYOK call with no managed attempt)."
+ },
+ "provider_access": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "OWN_DEPLOYMENT",
+ "AUTHORIZED_WHOLESALE",
+ "CUSTOMER_BYOK",
+ "RESTRICTED",
+ "UNVERIFIED",
+ null
+ ],
+ "description": "The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one."
+ },
+ "rate_version": {
+ "type": "string",
+ "description": "The retail rate-card version the usage was priced against (the settle request's retail.version)."
+ },
+ "usage": {
+ "type": "object",
+ "description": "The measured token counts, the same shape as billing.credit-hold-settle-request@1's usage.",
+ "required": [
+ "input_tokens",
+ "cached_read_tokens",
+ "cache_write_tokens",
+ "output_tokens"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "input_tokens": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "cached_read_tokens": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "cache_write_tokens": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "output_tokens": {
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ },
+ "charge_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "The charge the settlement recorded, integer nano-USD (D1). Usage beyond the hold and free balance is separately shortfall_nano_usd."
+ },
+ "supply_cost_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK."
+ },
+ "shortfall_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1)."
+ },
+ "released_nano_usd": {
+ "type": "string",
+ "pattern": "^[0-9]{1,19}$",
+ "description": "Hold amount returned to the account, integer nano-USD (D1)."
+ },
+ "byok": {
+ "type": "boolean",
+ "description": "True when the caller supplied their own provider key; the retail charge is 0."
+ },
+ "sandbox": {
+ "type": "boolean",
+ "description": "True when the hold was funded from usd_credit_sandbox (BILLING_CREDITS_SANDBOX), never paid credit."
+ }
+ }
+ }
+ },
"billing.admin-request": {
"billing.admin-request": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "billing",
"owner": "billing",
@@ -27454,6 +27589,11 @@
@@ -27454,6 +27589,11 @@
"type": "string",
"type": "string",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
+ },
+ "sandbox": {
+ "type": "boolean",
+ "default": false,
+ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."
}
}
}
}
}
}
@@ -27705,6 +27845,11 @@
@@ -27705,6 +27845,11 @@
"type": "string",
"type": "string",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
+ },
+ "sandbox": {
+ "type": "boolean",
+ "default": false,
+ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."
}
}
}
}
}
}
@@ -100477,7 +100622,7 @@
@@ -100477,7 +100622,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/billing/credit-sandbox-grant-request.v1.json",
"$id": "https://openvibe.network/contracts/billing/credit-sandbox-grant-request.v1.json",
"title": "BillingCreditSandboxGrantRequest",
"title": "BillingCreditSandboxGrantRequest",
- "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).",
+ "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.",
"type": "object",
"type": "object",
"required": [
"required": [
"subject",
"subject",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Actor API",
"title": "OpenVibe.Actor API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"title": "OpenVibe.AI API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bench API",
"title": "OpenVibe.Bench API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Billing API",
"title": "OpenVibe.Billing API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3104,6 +3104,11 @@
@@ -3104,6 +3104,11 @@
"type": "string",
"type": "string",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"pattern": "^[a-z][a-z0-9-]{0,39}$",
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
"description": "Which metered service spends the credit (D9): ai, run, ... Defaults to ai."
+ },
+ "sandbox": {
+ "type": "boolean",
+ "default": false,
+ "description": "D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false."
}
}
}
}
},
},
@@ -3369,7 +3374,7 @@
@@ -3369,7 +3374,7 @@
},
},
"billing.credit-sandbox-grant-request.v1": {
"billing.credit-sandbox-grant-request.v1": {
"title": "BillingCreditSandboxGrantRequest",
"title": "BillingCreditSandboxGrantRequest",
- "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).",
+ "description": "billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.",
"type": "object",
"type": "object",
"required": [
"required": [
"subject",
"subject",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Blog API",
"title": "OpenVibe.Blog API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bot API",
"title": "OpenVibe.Bot API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Chat API",
"title": "OpenVibe.Chat API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Codes API",
"title": "OpenVibe.Codes API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Community API",
"title": "OpenVibe.Community API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Coupons API",
"title": "OpenVibe.Coupons API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Deals API",
"title": "OpenVibe.Deals API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Domains API",
"title": "OpenVibe.Domains API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Events API",
"title": "OpenVibe.Events API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Food API",
"title": "OpenVibe.Food API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Games API",
"title": "OpenVibe.Games API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Host API",
"title": "OpenVibe.Host API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Inventory API",
"title": "OpenVibe.Inventory API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Live API",
"title": "OpenVibe.Live API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.MediaHub API",
"title": "OpenVibe.MediaHub API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Media API",
"title": "OpenVibe.Media API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Network API",
"title": "OpenVibe.Network API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.News API",
"title": "OpenVibe.News API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenRestream API",
"title": "OpenRestream API",
- "version": "0.286.0",
- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Play API",
"title": "OpenVibe.Play API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Quest API",
"title": "OpenVibe.Quest API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Report API",
"title": "OpenVibe.Report API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Reviews API",
"title": "OpenVibe.Reviews API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Run API",
"title": "OpenVibe.Run API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Search API",
"title": "OpenVibe.Search API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Services API",
"title": "OpenVibe.Services API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Sources API",
"title": "OpenVibe.Sources API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Space API",
"title": "OpenVibe.Space API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tips API",
"title": "OpenVibe.Tips API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Today API",
"title": "OpenVibe.Today API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tools API",
"title": "OpenVibe.Tools API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Trade API",
"title": "OpenVibe.Trade API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.VIP API",
"title": "OpenVibe.VIP API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Vision API",
"title": "OpenVibe.Vision API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Watch API",
"title": "OpenVibe.Watch API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Wiki API",
"title": "OpenVibe.Wiki API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Work API",
"title": "OpenVibe.Work API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Zone API",
"title": "OpenVibe.Zone API",
- "version": "0.286.0",
- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.286.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.287.0",
+ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.287.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -163890,6 +163890,74 @@ export interface BillingReceiptExternalPayload {
@@ -163890,6 +163890,74 @@ export interface BillingReceiptExternalPayload {
};
};
}
}
+/** [email protected] (owner: billing) */
+/**
+ * billing.credit.settled v1 (OpenVibe.Billing server/ops/credits.js settleHold(); written with the settlement row in the settle transaction): a Credits hold was settled once. It is AGGREGATE-ONLY on purpose: it carries no subject, no project_id and no account id, so a consumer can count services, routes and money but cannot reconstruct a person's statement; per-person statements are read from Billing's own ledger. OpenVibe.Report consumes it for aggregate analytics. Money is integer nano-USD as decimal strings (D1: never a float). Envelope: subject { type: credit-settlement, id: stl_… }, visibility internal, priority important, actor service:billing.
+ */
+export interface BillingCreditSettledPayload {
+ /**
+ * ULID settlement id, the same one the settle result and Billing's statement use.
+ */
+ settlement_id: string;
+ /**
+ * The settled hold.
+ */
+ hold_id: string;
+ /**
+ * The hold's service (D9): which metered service spent the credit, e.g. ai. Read from the hold; the settle request does not carry it.
+ */
+ service: string;
+ /**
+ * When the settlement committed (the settlement row's created_at).
+ */
+ settled_at: string;
+ /**
+ * The answering attempt's deployment id, '<provider>:<model>' as sent in the settle request's attempts[].deployment_id; null when no attempt answered (a cache hit or a BYOK call with no managed attempt).
+ */
+ deployment_id: string | null;
+ /**
+ * The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one.
+ */
+ provider_access: "OWN_DEPLOYMENT" | "AUTHORIZED_WHOLESALE" | "CUSTOMER_BYOK" | "RESTRICTED" | "UNVERIFIED" | null;
+ /**
+ * The retail rate-card version the usage was priced against (the settle request's retail.version).
+ */
+ rate_version: string;
+ /**
+ * The measured token counts, the same shape as billing.credit-hold-settle-request@1's usage.
+ */
+ usage: {
+ input_tokens: number;
+ cached_read_tokens: number;
+ cache_write_tokens: number;
+ output_tokens: number;
+ };
+ /**
+ * The charge the settlement recorded, integer nano-USD (D1). Usage beyond the hold and free balance is separately shortfall_nano_usd.
+ */
+ charge_nano_usd: string;
+ /**
+ * What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK.
+ */
+ supply_cost_nano_usd: string;
+ /**
+ * Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1).
+ */
+ shortfall_nano_usd: string;
+ /**
+ * Hold amount returned to the account, integer nano-USD (D1).
+ */
+ released_nano_usd: string;
+ /**
+ * True when the caller supplied their own provider key; the retail charge is 0.
+ */
+ byok: boolean;
+ /**
+ * True when the hold was funded from usd_credit_sandbox (BILLING_CREDITS_SANDBOX), never paid credit.
+ */
+ sandbox: boolean;
+}
+
/** [email protected] (owner: billing) */
/** [email protected] (owner: billing) */
/**
/**
* billing.admin-request@1: bodies of billing.ledger.admin on OpenVibe.Billing (operators). POST /api/v1/admin/freeze: { on, reason? } (unfreezing processes the provider deliveries stored meanwhile; allowed while frozen). POST /api/v1/admin/adjustments: { from, to, amount, reason, relates_to? } moves value between two accounts of one currency. POST /api/v1/purchases/settle: { provider, provider_ref, subject?, amount_cents, bits, intent_id?, test? } books a provider receipt. POST /api/v1/admin/provider-events/:id/reprocess, POST /api/v1/admin/sweep and the GETs (freeze, reconcile, provider-events, import-holds) take no body. Adjustments and settlements need an Idempotency-Key and are refused while frozen.
* billing.admin-request@1: bodies of billing.ledger.admin on OpenVibe.Billing (operators). POST /api/v1/admin/freeze: { on, reason? } (unfreezing processes the provider deliveries stored meanwhile; allowed while frozen). POST /api/v1/admin/adjustments: { from, to, amount, reason, relates_to? } moves value between two accounts of one currency. POST /api/v1/purchases/settle: { provider, provider_ref, subject?, amount_cents, bits, intent_id?, test? } books a provider receipt. POST /api/v1/admin/provider-events/:id/reprocess, POST /api/v1/admin/sweep and the GETs (freeze, reconcile, provider-events, import-holds) take no body. Adjustments and settlements need an Idempotency-Key and are refused while frozen.
@@ -164631,6 +164699,10 @@ export interface BillingCreditHold {
@@ -164631,6 +164699,10 @@ export interface BillingCreditHold {
* Which metered service spends the credit (D9): ai, run, ... Defaults to ai.
* Which metered service spends the credit (D9): ai, run, ... Defaults to ai.
*/
*/
service?: string;
service?: string;
+ /**
+ * D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false.
+ */
+ sandbox?: boolean;
}
}
/** [email protected] (owner: billing) */
/** [email protected] (owner: billing) */
@@ -164723,6 +164795,10 @@ export interface BillingCreditHoldCreateRequest {
@@ -164723,6 +164795,10 @@ export interface BillingCreditHoldCreateRequest {
* Which metered service spends the credit (D9): ai, run, ... Defaults to ai.
* Which metered service spends the credit (D9): ai, run, ... Defaults to ai.
*/
*/
service?: string;
service?: string;
+ /**
+ * D10. A sandbox caller's hold draws on that person's sandbox credit for the project (account kind usd_credit_sandbox, owner subject:project), never on real Credits, and a real hold never draws on sandbox credit. Sandbox grants (billing.credit-sandbox-grant-request@1) land in that sandbox account. Optional; defaults to false.
+ */
+ sandbox?: boolean;
}
}
/** [email protected] (owner: billing) */
/** [email protected] (owner: billing) */
@@ -285250,7 +285326,7 @@ export interface TodayAgenda {
@@ -285250,7 +285326,7 @@ export interface TodayAgenda {
/** [email protected] (owner: billing) */
/** [email protected] (owner: billing) */
/**
/**
- * billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9).
+ * billing.credit-sandbox-grant-request@1: POST /internal/credits/sandbox/grants, synthetic credit for tests and staging. Billing answers only when BILLING_CREDITS_SANDBOX=1; the grant is a test transaction (D9). D10: the grant lands in the subject's sandbox credit account for the project (account kind usd_credit_sandbox, owner subject:project), and only a sandbox hold (billing.credit-hold-create-request@1 sandbox: true) draws on it; real Credits are never touched.
*/
*/
export interface BillingCreditSandboxGrantRequest {
export interface BillingCreditSandboxGrantRequest {
subject: SubjectRef;
subject: SubjectRef;
@@ -46,7 +46,8 @@
@@ -46,7 +46,8 @@
"billing.cashout.paid",
"billing.cashout.paid",
"billing.cashout.denied",
"billing.cashout.denied",
"billing.staff.action",
"billing.staff.action",
- "billing.receipt.external"
+ "billing.receipt.external",
+ "billing.credit.settled"
],
],
"eventsConsumed": [],
"eventsConsumed": [],
"namespacesOwned": [
"namespacesOwned": [
@@ -23,7 +23,8 @@
@@ -23,7 +23,8 @@
"report.index_document.upserted"
"report.index_document.upserted"
],
],
"eventsConsumed": [
"eventsConsumed": [
- "ai.call.recorded"
+ "ai.call.recorded",
+ "billing.credit.settled"
],
],
"namespacesOwned": [
"namespacesOwned": [
"report.*"
"report.*"
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.286.0",
+ "version": "0.287.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
"types": "generated/typescript/index.d.ts",