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

# billing.credit-hold-create-request@1 · OpenVibe.Services

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

# BillingCreditHoldCreateRequest `billing.credit-hold-create-request@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: internal
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/billing/credit-hold-create-request.v1.json`](/docs/contracts/billing.credit-hold-create-request.json)

billing.credit-hold-create-request@1: body of POST /internal/credits/holds. Reserves inference credit up to max\_nano\_usd against a Balance account, priced at the given immutable rate version. With project\_id the hold spends that project's Balance; without it the hold is personal and spends the subject's own Balance (D12). An app subject always names its project.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `idempotency_key` | string | yes |  | - `pattern ^[A-Za-z0-9._:-]{8,128}$` |
| `subject` | [identity.subject-ref](/docs/contracts/identity.subject-ref) | yes |  |  |
| `project_id` | string |  | The project whose Balance the hold spends. Optional: without it the hold is personal, on the subject's own Balance. Required when the subject is an app. | - `pattern ^prj_[0-9A-HJKMNP-TV-Z]{26}$` |
| `credential_id` | string \| null |  |  | - `pattern ^cred_[0-9A-HJKMNP-TV-Z]{26}$` |
| `max_nano_usd` | `https://openvibe.network/contracts/billing/credit-hold-create-request.v1.json#/$defs/money-nano-usd` | yes |  |  |
| `rate_version` | string | yes |  |  |
| `request_fingerprint` | string | yes |  | - `maxLength 1024` |
| `service` | string |  | Which metered service spends the credit (D9): ai, run, ... Defaults to ai. | - `pattern ^[a-z][a-z0-9-]{0,39}$` |
| `sandbox` | boolean |  | 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. | - `default false` |

## Examples

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

 Valid: minimal

~~~~
{
  "idempotency_key": "hold-key-001",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "max_nano_usd": "100000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-001"
}
~~~~

Valid: personal-hold

~~~~
{
  "idempotency_key": "hold-key-personal-001",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "max_nano_usd": "100000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-personal-001",
  "service": "ai"
}
~~~~

Valid: sandbox

~~~~
{
  "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
}
~~~~

Valid: with-credential

~~~~
{
  "idempotency_key": "hold-key-002",
  "subject": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "credential_id": "cred_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "max_nano_usd": "50000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-002"
}
~~~~

Rejected: app-without-project

~~~~
{
  "idempotency_key": "hold-key-app-001",
  "subject": {
    "type": "app",
    "id": "app_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "max_nano_usd": "50000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-app-001"
}
~~~~

Rejected: bad-subject

~~~~
{
  "idempotency_key": "hold-key-001",
  "subject": {
    "type": "person",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "max_nano_usd": "100000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-001"
}
~~~~

Rejected: missing-key

~~~~
{
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "max_nano_usd": "100000000",
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-001"
}
~~~~

Rejected: money-number

~~~~
{
  "idempotency_key": "hold-key-001",
  "subject": {
    "type": "user",
    "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "max_nano_usd": 100000000,
  "rate_version": "rr-2026-11-03-001",
  "request_fingerprint": "fp-chat-001"
}
~~~~

Rejected: sandbox-string

~~~~
{
  "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"
}
~~~~

## Validate

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