BillingCreditSettledPayload billing.credit.settled@1
Generated at from
openvibe-contracts v0.419.0 and
openvibe-sdk v0.161.0.
- Version
- 1.0.0
- Owner
- billing
- Visibility
- first-party
- Status
- active
- Compatibility
- backward
- Schema
https://openvibe.network/contracts/events/payloads/billing.credit.settled.v1.json
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.
Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
settlement_id | string | yes | ULID settlement id, the same one the settle result and Billing's statement use. |
|
hold_id | string | yes | The settled hold. |
|
service | string | yes | 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 | string | yes | When the settlement committed (the settlement row's created_at). |
|
deployment_id | string | null | yes | 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 | enum | yes | The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one. |
|
rate_version | string | yes | The retail rate-card version the usage was priced against (the settle request's retail.version). | |
usage | object | yes | The measured token counts, the same shape as billing.credit-hold-settle-request@1's usage. |
|
usage.input_tokens | integer | yes |
| |
usage.cached_read_tokens | integer | yes |
| |
usage.cache_write_tokens | integer | yes |
| |
usage.output_tokens | integer | yes |
| |
charge_nano_usd | string | yes | 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 | string | yes | What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK. |
|
shortfall_nano_usd | string | yes | Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1). |
|
released_nano_usd | string | yes | Hold amount returned to the account, integer nano-USD (D1). |
|
byok | boolean | yes | True when the caller supplied their own provider key; the retail charge is 0. | |
sandbox | boolean | yes | True when the hold was funded from usd_credit_sandbox (BILLING_CREDITS_SANDBOX), never paid credit. |
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: byok-sandbox
{
"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
}Valid: managed-ai
{
"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
}Rejected: money-number
{
"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
}Rejected: subject-included
{
"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"
}
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('billing.credit.settled@1', value); // { valid, errors: [{ path, message }] }