---
title: "billing.credit.settled@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/billing.credit.settled"
updated: null
---

# billing.credit.settled@1 · OpenVibe.Services

HTML: [billing.credit.settled@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/billing.credit.settled)

# BillingCreditSettledPayload `billing.credit.settled@1`

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

- Version: 1.0.0
- Owner: billing
- Visibility: first-party
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/events/payloads/billing.credit.settled.v1.json`](/docs/contracts/billing.credit.settled.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. | - `pattern ^stl_[0-9A-HJKMNP-TV-Z]{26}$` |
| `hold_id` | string | yes | The settled hold. | - `pattern ^hld_[0-9A-HJKMNP-TV-Z]{26}$` |
| `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. | - `pattern ^[a-z][a-z0-9-]{0,39}$` |
| `settled_at` | string | yes | When the settlement committed (the settlement row's created\_at). | - `format date-time` |
| `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). | - `maxLength 256` |
| `provider_access` | enum | yes | The answering attempt's commercial route (D3); null when no attempt answered or its route did not state one. | - `one of "OWN_DEPLOYMENT", "AUTHORIZED_WHOLESALE", "CUSTOMER_BYOK", "RESTRICTED", "UNVERIFIED", null` |
| `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. | - `no other fields` |
| `usage.input_tokens` | integer | yes |  | - `minimum 0` |
| `usage.cached_read_tokens` | integer | yes |  | - `minimum 0` |
| `usage.cache_write_tokens` | integer | yes |  | - `minimum 0` |
| `usage.output_tokens` | integer | yes |  | - `minimum 0` |
| `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. | - `pattern ^[0-9]{1,19}$` |
| `supply_cost_nano_usd` | string | yes | What the route cost OpenVibe at supply, integer nano-USD (D1); 0 for BYOK. | - `pattern ^[0-9]{1,19}$` |
| `shortfall_nano_usd` | string | yes | Usage beyond the hold and the free balance: owed, not collected (nano-USD, D1). | - `pattern ^[0-9]{1,19}$` |
| `released_nano_usd` | string | yes | Hold amount returned to the account, integer nano-USD (D1). | - `pattern ^[0-9]{1,19}$` |
| `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 }] }
~~~~
