Price a generation before submitting it, show the customer that price, and follow its hold through to a charge or refund. Published model prices, quotes and the itemized ledger all use credits.
Each model publishes its billing unit. Read the current catalog rather than keeping a second price list in your application.
Modality
Billing unit
How the charge is calculated
Image
per_image
The selected model and quality-tier price for each image.
Video
per_clip
The published price assumes baseline_seconds, normally 5 seconds. Charge ceil(credits × duration_seconds / baseline_seconds) for the requested duration.
Text to speech
per_character
The headline credits compares a 1,000-character script. Actual charge is max(minimum_credits, ceil(characters / characters_per_credit)); the minimum bills a short line as 200 characters. Count Unicode characters, not bytes.
3D and other flat-rate generation
per_generation
One published rate per generation; inspect the selected model's cost.unit.
Image
Video
Audio
3D
48
74
17
2
See Model APIs for the full per-model tables. A missing cost means the price is not published; display an unknown price, not zero. Nolgia does not expose a GPU-time billing fallback.
Nolgia takes a credit hold when the request is accepted. Delivery consumes that hold; it does not create a second charge. A failed job normally releases the hold, subject to the policy-refusal exception below.
Setting
Effect on credits
Image count
Each requested image contributes its model price.
Video duration
Scales the selected per-clip price by duration_seconds / baseline_seconds, rounded up.
Speech text
Uses the Unicode character count and the published minimum.
quality
Selects the complete per-tier price from quality.options[].credits; do not add that value to the base price. Video tiers use the same clip baseline.
render_quality
GPT Image 2.5's xhigh and max add the published credits per image, independently of the native/2k/4k quality tier. auto, low, medium and high do not add credits.
generate_audio
Where audio_surcharge is published, the default price includes it. generate_audio=false subtracts it before duration scaling.
A separate agent_turn ledger row. A turn charges at least the published per-turn rate; a more expensive turn uses max(flat_rate(model), ceil(provider_cost_usd / 0.01)). Its row supplies tokens and provider_cost_usd when those explain a charge above the flat rate.
Generation started by an agent
Its own generation hold and ledger row, separate from the turn that requested it.
Studio render
The ledger reserves a render kind, but composition renders currently take no credit hold. Generating the source images, clips or narration is billed separately.
Credits move from available to held, then charged or refunded
The hold is released; check failure.credits_refunded.
409 duplicate submission
No new hold and no second charge. Follow the existing job_id.
408 request or wait timeout
The timeout response itself adds no charge. A wait timeout does not cancel or refund the accepted job; that job can still finish and settle its existing hold.
This trimmed flux-pro entry preserves the real cost and quality values from the production model fixture. The public response wraps entries in models; other models and other pricing fields are omitted here.
The catalog id a generation request sends as model.
display_name
string
Yes
What to call this model on a customer-facing surface. Always present: no published model is nameless, because a raw id is sometimes a provider route path and must never be rendered.
maker
string
No
The company that made the model (Google, Kuaishou, Black Forest Labs).…
summary
string
No
One sentence about the model. Absent until written; copy arrives incrementally, and an absent summary renders as nothing.
recommended
boolean
No
Mirrors Model.recommended — the pick for its modality.
video
VideoCapabilities
No
audio
AudioCapabilities
No
image
ImageCapabilities
No
references
ReferenceCapabilities
No
restore
boolean
No
Mirrors Model.restore.
remove_background
boolean
No
Mirrors Model.remove_background.
image_enhance
boolean
No
Mirrors Model.image_enhance.
image_expand
boolean
No
Mirrors Model.image_expand.
modality
Modality
Yes
min_tier
SubscriptionTier
Yes
Minimum subscription plan required to run this model; starter means every plan can.…
cost
ModelCost
No
quality
QualityCapabilities
No
three_d
ThreeDCapabilities
No
aspect_ratios
array of string
Yes
The output aspect ratios this model renders (video.aspect_ratios for video models, image.aspect_ratios for image models), as plain strings so one field spans both enums.…
render_quality
RenderQualityCapabilities
No
Mirrors image.render_quality from GET /models.…
inpaint_mask
boolean
No
Mirrors image.inpaint_mask from GET /models: this model can edit only PART of an image, guided by a mask.…
capabilities
array of VideoCapabilityTag
No
Mirrors Model.capabilities: the video capability CLASSES this model exists to serve, as opposed to the individual inputs it accepts.…
Field
Type
Required
Description
credits
integer
Yes
Credits charged per unit at the model's DEFAULT audio state.…
unit
ModelCostUnit
Yes
audio_surcharge
integer, nullable
No
Extra credits (per the model's unit) that a soundtrack adds, when the provider charges more to render audio.…
video_input_credits
integer, nullable
No
credits for a request that carries a reference video, at the model's default tier, when the provider bills a video input at a different rate.…
input_image_credits
integer, nullable
No
Extra credits for each input image past free_input_images, on a model that charges for input images.…
free_input_images
integer, nullable
No
Present with input_image_credits: how many input images a request carries before the surcharge starts.
baseline_seconds
integer, nullable
No
Present only when unit is per_clip. The clip duration in seconds that credits assumes. The actual charge scales with the requested duration as ceil(credits * duration_seconds / baseline_seconds).
characters_per_credit
integer, nullable
No
Present only when unit is per_character.…
minimum_credits
integer, nullable
No
Present only when unit is per_character.…
Field
Type
Required
Description
id
string
Yes
Tier identifier accepted by the quality request parameter.
credits
integer
Yes
Credits charged per the model's cost.unit when this tier is selected (for video, per baseline_seconds clip), at the model's DEFAULT audio state.…
audio_surcharge
integer, nullable
No
Extra credits this tier's soundtrack adds when the provider charges more for audio.…
video_input_credits
integer, nullable
No
Credits per baseline_seconds clip at this tier when the request carries a reference video (video_asset_ids / video_urls), for a model whose provider bills a video input at a different rate than a text or image render.…
premium
boolean
Yes
Marks a premium (highest-quality, higher credit cost) tier so clients can present it distinctly from standard options.
aspect_ratios
array of string
No
When present, the tier renders at these aspect ratios ONLY (a subset of the model's video.aspect_ratios); a request pairing the tier with any other aspect_ratio is refused with a 400 before any credits are held.…
kind and the matching generation body, such as image
Result
The exact credits the same settings will hold, plus a confirmation token you may return on submit
Re-quote when
The request changes or expires_at passes
These examples use the generated clients. The CLI currently has no dedicated quote command; its tab uses curl with the same NOLGIA_TOKEN. The response below is a production capture, not a claim that each language example was run live.
shellQuote an image example
$ curl --fail-with-body -sS https://api.nolgia.ai/v1/jobs/cost \
-H "Authorization: Bearer $NOLGIA_TOKEN"\
-H "Content-Type: application/json"\
-d '{"kind":"image","image":{"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"}}'
shellQuote from the terminal example
$ # No dedicated nolgia quote command; call the quote endpoint directly.$ curl --fail-with-body -sS https://api.nolgia.ai/v1/jobs/cost \
-H "Authorization: Bearer $NOLGIA_TOKEN"\
-H "Content-Type: application/json"\
-d '{"kind":"image","image":{"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"}}'
TypeScriptQuote an image example
import{createNolgiaClient}from"@nolgia/sdk";constnolgia=createNolgiaClient(process.env.NOLGIA_TOKEN!);const{data: quote,error}=awaitnolgia.POST("/jobs/cost",{body:{kind:"image",image:{model:"flux-pro",prompt:"a paper-cut mountain range at dawn",num_images: 1},},});if(error)thrownewError(`${error.title}: ${error.detail??""}`);console.log(quote.credits,quote.expires_at);
PythonQuote an image example
importosfromnolgiaimportAuthenticatedClientfromnolgia.api.jobsimportquote_job_costfromnolgia.modelsimportGenerateImageRequest,ImageModel,JobCostKind,JobCostQuote,JobCostRequestclient=AuthenticatedClient(base_url="https://api.nolgia.ai/v1",token=os.environ["NOLGIA_TOKEN"])quote=quote_job_cost.sync(client=client,body=JobCostRequest(kind=JobCostKind("image"),image=GenerateImageRequest(model=ImageModel("flux-pro"),prompt="a paper-cut mountain range at dawn"),))ifnotisinstance(quote,JobCostQuote):raiseSystemExit(f"refused: {quote}")print(quote.credits_,quote.expires_at)
RustQuote an image example
usenolgia_client::{types,ClientBuilder};#[tokio::main]asyncfnmain()-> Result<(),Box<dynstd::error::Error>>{letclient=ClientBuilder::new("https://api.nolgia.ai/v1").bearer_token(std::env::var("NOLGIA_TOKEN")?).build()?;letprompt: types::GenerateImageRequestPrompt="a paper-cut mountain range at dawn".parse()?;letimage: types::GenerateImageRequest=types::GenerateImageRequest::builder().model("flux-pro").prompt(Some(prompt)).num_images(1u64).try_into()?;letquote=client.quote_job_cost().body_map(|b|b.kind(types::JobCostKind::Image).image(Some(image))).send().await?.into_inner();println!("{}{}",quote.credits,quote.expires_at);Ok(())}
The real cost-image.json capture quotes one native flux-pro image. Its prompt differs from the reusable example above, and its opaque confirmation token is redacted.
The model id the quote is for, after defaulting — not necessarily the one you sent.
credits
integer
Yes
Display credits. This is the number the submit will hold, computed by the same pricer the submit path uses, for exactly these settings. It is what to show the customer.
basis
one of one_generation, set_run
Yes
Whether credits covers one generation or a whole set run.
members
integer, nullable
No
Number of set members credits covers. Present only when basis is set_run.
duration_seconds
integer, nullable
No
The billed duration the price is for, on a video quote.
quality
string, nullable
No
The resolved quality tier the price is for, when the model has one.
settings
array of JobCostSetting
Yes
The settings that made this price, in the order a dialog should show them. Human-readable; do not parse it.
balance_credits
integer, nullable
No
The wallet balance this quote was compared against, when one could be read.
sufficient_credits
boolean
Yes
Whether the balance covers credits right now. Advisory — the submit re-checks.
confirmation_token
string
Yes
Short-lived, single-request proof that this price was quoted. Send it back as confirmation_token on the matching generate request. Opaque: do not parse or construct it.
expires_at
string
Yes
After this the token is refused and a submit carrying it fails with confirmation_rejected. Re-quote.
Confirmation gate: quote the request, show the price, and submit with its token
Return confirmation_token on the unchanged generation body if you want submission bound to the quoted request and price. The token is optional; when supplied, a stale, malformed, foreign or mismatched token fails with 422 confirmation_rejected. Quote again. sufficient_credits is advisory because submission checks the balance again.
Personal Access Tokens you create spend available_for_api. The app, the Nolgia Agent, organization API keys and connected assistants (ChatGPT, Claude or any MCP client connected through OAuth) spend available_for_app. available_for_credential is the figure for the credential that made the request, and credential_channel names its channel. Monthly app_subscription credits expire at the subscription cycle end; shared_topup credits do not expire and are spendable by either surface.
Monthly app-only credits that expire at the subscription cycle end.
shared_topup
integer
Yes
Shared app/API prepaid credits that do not expire.
total
integer
Yes
available_for_app
integer
Yes
App-visible credits; subscription bucket plus shared top-up overflow.
available_for_api
integer
Yes
API prepaid credits; shared top-up only at launch.
credential_channel
CreditChannel
No
available_for_credential
integer
No
What the credential that made this request can spend: available_for_app on the app channel, available_for_api on the API channel (see credential_channel).…
buckets
array of CreditBalanceBucket
Yes
scope
BillingScope
No
organization_id
string
No
Set when scope is organization: the balances above are the ORGANIZATION's shared pool (the caller's personal wallets are not consulted inside an organization) and user_id is the caller.
seats
integer
No
Seats on the organization's subscription; organization scope only.
seat_limit
integer, nullable
No
The organization's seat cap (null = unlimited); organization scope only.
member_budget
integer, nullable
No
The caller's monthly credit budget in the organization (null = unlimited); organization scope only.
member_spent_this_month
integer
No
What the caller has spent from the organization's pool this UTC calendar month (held plus consumed reservations); organization scope only.
GET /billing/transactions returns newest-first rows. The debit when a hold is taken is the charge; completion writes no second debit. Releasing it writes a refund for the same amount. balance_after belongs to the particular wallet_id, not to the combined account balance.
This schema-built example uses the documented Quick Start amounts: a 12-credit veo-3.1-lite four-second charge and its 12-credit refund. The row ids, timestamps and wallet balances are illustrative; this is not a captured ledger response.
Opaque pagination cursor returned by a prior response.
limit
query
No
Rows per page.
from
query
No
Inclusive window start (RFC 3339). Omit for no lower bound.
to
query
No
Exclusive window end (RFC 3339). Omit for no upper bound.
kind
query
No
Only rows of this kind.
wallet
query
No
Only rows on this wallet type (default all).
member_id
query
No
Organization context only: rows caused by this member. Owner, admin and billing roles may name any member; other roles only themselves. 400 in the personal space.
Field
Type
Required
Description
items
array of CreditTransaction
Yes
Rows newest first.
next_cursor
string, nullable
Yes
Pass as cursor for the next page; null on the last page.
scope
BillingScope
Yes
organization_id
string
No
Set when scope is organization.
Field
Type
Required
Description
id
string
Yes
occurred_at
string
Yes
kind
CreditTransactionKind
Yes
wallet
CreditTransactionWallet
Yes
wallet_id
string
Yes
wallet_expires_at
string, nullable
No
When the wallet's credits expire (subscription wallets); null for the top-up wallet.
credits
integer
Yes
Signed movement. Negative for charges and debits, positive for grants, top-ups, redemptions and refunds.
balance_after
integer
Yes
The wallet's balance after this row (running sum of the wallet identified by wallet_id).
description
string
Yes
Plain-language label, for example Video generation · seedance-2.5 · 5 s or Refund · Agent turn. Never contains an em dash.
model
string
No
Catalog model id when the row charges or refunds a generation, and the agent brain (for example claude-opus-5-5) when it charges or refunds an agent turn. Label it client-side.
preset
string
No
Preset slug when the generation was launched from a preset.
job_id
string
No
The generation job behind a generation charge or its refund.
session_id
string
No
The agent chat session behind an agent_turn charge or its refund.
tokens
integer
No
Tokens the agent turn behind this row reported, across every iteration of its reasoning loop.…
provider_cost_usd
number
No
Measured provider cost in US dollars of the agent turn behind this row.…
render_id
string
No
The render behind a render charge or its refund.
member
CreditTransactionMember
No
meter
CreditTransactionMeter
No
Kind
Meaning
grant
Monthly plan credits or credits granted by Nolgia.
topup
A credit purchase.
redeem
A credit-code redemption.
generation
A generation charge.
agent_turn
A chat turn charge.
render
Reserved for composition-render charges; renders currently take no hold.
GET /billing/transactions/summary rolls up the same rows and scope. It defaults to the current UTC month; credits_used and credits_refunded are positive totals, while by_kind[].credits is signed.
See nolgia.ai/pricing for current plans and credit purchases. Subscriptions supply monthly app credits; top-ups supply shared prepaid credits. A model's min_tier and its credit price are separate: adding credits does not unlock an out-of-plan model.
Operation
Use it for
GET /billing/subscription
Read the plan, status and current period end.
POST /billing/portal-link
Open the returned expiring Stripe Customer Portal URL to manage billing.
POST /credits/redeem
Redeem an issued code into shared top-up credits, once per account.
GET /billing/auto-refresh
Read automatic top-up settings.
PUT /billing/auto-refresh
Update whether auto-refresh is enabled, its threshold and purchase amount.
A code refusal returns 404 for an unknown code, 410 for a deactivated, expired or exhausted code, 409 if this account already redeemed it, and 429 for rate-limited attempts. A repeated redemption can never grant credits twice.
In an organization, spending uses the organization's wallets, not your personal balance. GET /organizations/{id}/credits reports the shared pool, seats, and monthly member budgets. An unlimited budget is null; the member's month-to-date spend includes both held and consumed reservations.
Role
Credit and usage visibility
Owner, admin, billing
The organization pool and every member's rows.
Member, viewer
The shared pool and their own member row or spend.
Non-member
404; the organization is not exposed.
GET /organizations/{id}/usage groups consumed credits by member, model or UTC day; it defaults to the current UTC calendar month and excludes held and released reservations. Usage and activity explains why these totals differ from gross ledger charges. For organization contracts, see the Enterprise option on Pricing.