External wallets
Connect a dedicated Nodaro Cloud deployment to your own shared wallet, which reserves, settles and reports each customer's credits across all your products.
Available on Nodaro Cloud
An external wallet is a service you run that holds each customer's shared budget, and that a dedicated Nodaro Cloud deployment consults before it spends. Nodaro asks the wallet to reserve credits before each generation, settles the exact amount afterwards, and reads the balance to show it to the customer. The deployment's billing account still pays for platform usage from its prepaid pool; the wallet decides how much of that each customer may use, across all your products.
How it fits together
- A billing account pays. The deployment names one billing account (
billing.payerAccountin its surface profile), whose prepaid pool pays for every action on the deployment. See Editions and surface profiles. - SSO identifies the customer. Customers sign in through the deployment's SSO provider. The provider's subject for a customer, sent as
sso_subject, is how your wallet recognizes the customer. - The wallet decides. For every single-node request and every workflow node, Nodaro checks the billing account's prepaid pool, then asks your wallet to reserve against the customer's shared budget. The customer's local Nodaro credit balance plays no part.
An empty prepaid pool can stop a request before the wallet is asked. Once asked, the wallet's decision is final for the customer's shared budget.
Reserve
A customer starts a generation. Nodaro sends reserve with an operation_id and an amount, and your wallet holds that amount atomically and answers allow or deny.
Run
On allow, the model runs. On anything else, nothing is sent to the model.
Settle
When the work ends, Nodaro sends settle with the actual amount. Your wallet charges exactly that amount and releases the rest of the hold.
Show the balance
The studio asks your wallet for the customer's balance, and shows it in the deployment's display unit.
Configure the deployment
Set these variables on the API and on the workers:
| Variable | What it sets |
|---|---|
DEPLOYMENT_WALLET_URL | The wallet's endpoint. It must use HTTPS. |
DEPLOYMENT_WALLET_TOKEN | A dedicated server secret that Nodaro sends as a bearer token. |
DEPLOYMENT_WALLET_SSO_PROVIDER | The id of the SSO provider whose subjects identify customers. |
DEPLOYMENT_WALLET_TIMEOUT_MS | The time limit of each wallet call, from 1000 to 30000 milliseconds. The default is 10000. |
- Set the first three together. Leave all three unset to keep the deployment's existing billing.
- Turn off local allowances. The per-user allowance enforcement,
billing.allowances: "enforce", must be off. A configuration that combines the two is refused at activation. - Agree on the unit first. Before you activate the wallet, agree on the conversion between Nodaro credits and your product's budget. Set
billing.unitRateandbilling.unitLabelin the surface profile to match, so both products show the same figure.
The request contract
Nodaro sends every call as a POST with a JSON body that carries contract: 1 and unit: "nodaro_credit", and the header Authorization: Bearer <token>. The amounts are Nodaro credits. Never read them as your own product's units without an explicit conversion that your wallet owns.
Reserve
{
"contract": 1,
"unit": "nodaro_credit",
"action": "reserve",
"operation_id": "a3354131-4e5e-43a6-8f61-3914f09c658e",
"job_id": null,
"user_id": "5bf0d884-47b1-468e-a7b2-2433f957b267",
"sso_provider": "partner",
"sso_subject": "customer-123",
"model_identifier": "example-model",
"reserved_credits": 30
}| Field | Meaning |
|---|---|
operation_id | One usage record. A job or a workflow can contain several. |
sso_subject | The customer. It comes from trusted sign-in data that Nodaro's server manages, so use it to identify the customer. |
sso_provider, user_id | The SSO provider and the Nodaro user behind the request. |
model_identifier | The model being billed. |
reserved_credits | The whole number of credits to hold. |
Reserve the amount atomically against the customer's shared available budget before you answer. To allow the request:
{"contract":1,"unit":"nodaro_credit","operation_id":"a3354131-4e5e-43a6-8f61-3914f09c658e","decision":"allow","reserved_credits":30}For insufficient funds or an account that may not spend, answer HTTP 200 with the same envelope and "decision": "deny"; no amount is needed. Answer a service error with a status outside the 2xx range.
Nothing reaches the model unless your wallet allows it. A timeout, a malformed answer, a mismatched amount or id, a missing identity and a denial all stop the request. The request's Idempotency-Key header is <operation_id>:reserve.
Settle or release
When the work ends, Nodaro sends the same operation fields with "action": "settle" and actual_credits. Charge exactly that amount and release the rest of the hold. A settle of 0 releases everything.
{"contract":1,"unit":"nodaro_credit","operation_id":"a3354131-4e5e-43a6-8f61-3914f09c658e","settled":true,"actual_credits":12}- The key is
<operation_id>:settle. Delivery is at least once. A retry must return the original result without charging again. - Refuse conflicts. Reject a request for the same operation with a different identity, reservation ceiling or final amount.
- A settle can arrive before a delayed reserve. A settle of
0must create a permanent final record, even for an operation you do not know yet. A later reserve must never reopen it. - Holds never expire. A generation, and a human review of its result, can outlive any HTTP request. Keep each hold until it is settled, and keep your idempotency records. Never release an active hold because a callback is late.
Balance
{"contract":1,"unit":"nodaro_credit","action":"balance","user_id":"5bf0d884-47b1-468e-a7b2-2433f957b267","sso_provider":"partner","sso_subject":"customer-123"}{"contract":1,"unit":"nodaro_credit","sso_subject":"customer-123","available_credits":250}- Available means after holds.
available_creditsexcludes every outstanding hold, across all your products. - Fractions are allowed here. The balance may be fractional, so a remainder smaller than one billable credit can still be shown. Reserve and settle amounts are always whole credits.
- One figure in the studio. The studio converts the balance once into the deployment's display unit and hides its own per-user allowance display. An unavailable balance appears as unknown.
- Reserve decides races. When requests arrive at the same moment, the reserve call, not the balance, is authoritative.
Delivery and recovery
- Nodaro tries to deliver each settlement at once. If that fails, a worker that runs every minute retries it, with a backoff of up to one hour. Unacknowledged settlements are kept until they are delivered.
- Nodaro cancels on its own only the reservations that were never authorized. Authorized jobs that are running follow the normal job recovery.
- Never remove the wallet configuration, or point it to another wallet, while operations remain open. To rotate the token, rotate it on the same wallet.
Price discovery
GET /v1/deployment-billing/pricing returns the deployment's price list for your wallet's own display and planning. It needs the billing account's session or one of its billing integration keys.
| Field | Meaning |
|---|---|
creditCost | The base tariff of a model. |
creditIdentifier | The identifier that is billed. |
pricingBasis | What the base tariff assumes. |
pricing | For text models, the identifiers of each operation. Text models are listed as llm-chat at default settings. |
denomination | The credit unit and the display conversion. |
purchaseOptions | The standard top-ups in USD, with their effective price per credit. Separate commercial terms may apply. |
- Media variants and text operations resolve through the prices in effect. A variant without a configured price stays
null, with an error code. - Settings, quantity, duration and measured usage can change the final charge. Account with the reserve and settle amounts, never with a base tariff from this list.
- To detect changes, prefer a full request with
If-None-Match. Thesinceparameter follows the timestamps of price rows, and cannot see every change of runtime configuration.
Frequently asked questions
Related
External sign-in (SSO)
Credits
Editions and surface profiles
Credits
Last updated on
3D scene format
How a Nodaro 3D scene plan is built, from version 1 primitives and keyframes to version 2 GLB assets, semantic entities, camera tracks, shots and edit overlays.
Agent skills
Ready-made instruction files that teach coding agents to build on Nodaro with the SDK and OAuth, plus the Claude Code plugin, the SDK primer and Markdown docs.