BillingCreditHold billing.credit-hold@1

Generated at from openvibe-contracts v0.419.0 and openvibe-sdk v0.161.0.

Version
1.0.0
Owner
billing
Visibility
internal
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/billing/credit-hold.v1.json

billing.credit-hold@1: a reservation against an account's available inference credit. Holds are created before a request runs, may be extended while streaming, and are settled or released exactly once. Money fields are integer nano-USD, as strings.

Fields

FieldTypeRequiredDescriptionConstraints
hold_idstringyesULID hold id.
  • pattern ^hld_[0-9A-HJKMNP-TV-Z]{26}$
subjectidentity.subject-refyes
project_idstring | nullThe project whose Balance the hold spends. Null or absent for a personal hold on the subject's own Balance (D12); an app subject's hold always names its project.
  • pattern ^prj_[0-9A-HJKMNP-TV-Z]{26}$
credential_idstring | nullDeveloper credential the hold is scoped to, if any.
  • pattern ^cred_[0-9A-HJKMNP-TV-Z]{26}$
held_nano_usdhttps://openvibe.network/contracts/billing/credit-hold.v1.json#/$defs/money-nano-usdyes
available_nano_usdhttps://openvibe.network/contracts/billing/credit-hold.v1.json#/$defs/money-nano-usdyes
max_nano_usdhttps://openvibe.network/contracts/billing/credit-hold.v1.json#/$defs/money-nano-usd
rate_versionstringImmutable retail rate-card version the hold was priced against.
request_fingerprintstringOpaque fingerprint used to dedupe the same idempotency key.
  • maxLength 1024
lease_expires_atstringyes
  • format date-time
statusenum
  • one of "active", "extended", "settled", "released", "expired"
created_atstring
  • format date-time
servicestringWhich metered service spends the credit (D9): ai, run, ... Defaults to ai.
  • pattern ^[a-z][a-z0-9-]{0,39}$
sandboxbooleanD10. 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.
  • default false

Examples

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

Valid: active
{
  "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "credential_id": "cred_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "held_nano_usd": "100000000",
  "available_nano_usd": "75000000",
  "max_nano_usd": "100000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-001",
  "lease_expires_at": "2026-11-03T01:00:00.000Z",
  "status": "active",
  "created_at": "2026-11-03T00:00:00.000Z"
}
Valid: personal-hold
{
  "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPS",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": null,
  "held_nano_usd": "100000000",
  "available_nano_usd": "250000000",
  "max_nano_usd": "100000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-personal-001",
  "lease_expires_at": "2026-11-04T01:00:00.000Z",
  "status": "active",
  "created_at": "2026-11-04T00:00:00.000Z",
  "service": "ai"
}
Valid: sandbox
{
  "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
}
Valid: settled
{
  "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "subject": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "credential_id": null,
  "held_nano_usd": "50000000",
  "available_nano_usd": "0",
  "max_nano_usd": "50000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-002",
  "lease_expires_at": "2026-11-03T01:00:00.000Z",
  "status": "settled",
  "created_at": "2026-11-03T00:00:00.000Z"
}
Rejected: bad-status
{
  "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "held_nano_usd": "100000000",
  "available_nano_usd": "75000000",
  "lease_expires_at": "2026-11-03T01:00:00.000Z",
  "status": "closed"
}
Rejected: money-float
{
  "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "held_nano_usd": "100000000.5",
  "available_nano_usd": "75000000",
  "lease_expires_at": "2026-11-03T01:00:00.000Z"
}
Rejected: money-number
{
  "hold_id": "hld_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "held_nano_usd": 100000000,
  "available_nano_usd": "75000000",
  "lease_expires_at": "2026-11-03T01:00:00.000Z"
}
Rejected: sandbox-string
{
  "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"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('billing.credit-hold@1', value);   // { valid, errors: [{ path, message }] }