Skip to main content
The Aurous Labs API uses date-pinned versioning. Send Aurous-Version: 2026-05-15 (or any prior date) on every request to opt into a specific contract; we echo the applied version on every response. Missing the header falls back to your team’s default_api_version (current at signup). Breaking changes ship under a new date; non-breaking additions are listed under the current date.

2026-06-19 — Character synthesis is now asynchronous + character webhook events

POST /v1/characters with generate: true no longer blocks until the character is rendered. It returns immediately with status: "synthesizing"; the synthesis runs in the background and the character transitions to ready (or failed). Poll GET /v1/characters/:id, or subscribe to the new character webhook events.
  • POST /v1/characters. Now responds 201 with status: "synthesizing" instead of returning the finished character. An optional client_reference_id (≤ 256 chars) is echoed on the response and on every character webhook. Behavior change: callers that relied on the synchronous response must switch to polling GET /v1/characters/:id until status is ready or failed, or subscribe to webhooks. Applies across all version pins.
  • New webhook events. character.completed (reached ready; payload carries the reference renders), character.failed (provider error, moderation, or timeout — error_message carries a customer-safe code), and character.cancelled (DELETE /v1/characters/:id on an in-flight synthesis). Subscribe via the events array on a webhook endpoint, or in the dashboard webhook settings.

2026-06-03 — Documented platform defaults now applied to omitted generation params

POST /v1/images now applies the platform default for steps, guidance_scale, cfg_rescale, and denoise_strength when you omit the parameter and the selected style does not define its own default. Previously these defaults were documented on the request fields but only enforced by the dashboard, so an API caller who omitted them fell through to the provider’s raw default.
  • POST /v1/images. Omitting cfg_rescale resolves to 0.7, steps to 11, and guidance_scale to 4.3. Omitting denoise_strength on a request that has references resolves to 0.6 (it remains ignored on bare text-to-image requests). Precedence is unchanged: an explicit request value wins, then the selected style’s default, then the platform default.
  • No request or response shape change. No fields added or removed; the response continues to echo only the values you supplied — omitted params are resolved server-side and not reflected back.
This aligns behavior with the already-published default values on the request fields, so it applies across all version pins rather than shipping under a new date. The only observable change is for a caller who omitted cfg_rescale and relied on the provider’s raw default. Zero customers were affected at release time.

2026-05-24 — Embedding video rate removed; video_url input rejected

The embedding_pricing.video field on GET /v1/models has been removed. Embedding billing has always folded video_url input into the visual bucket — the provider extracts frames from videos and bills them as visual tokens. The previously published embedding_pricing.video rate never actually fired. To prevent the contract from misleading integrators, the field is now gone.
  • GET /v1/models. The embedding_pricing object on embedding-kind rows no longer contains a video key. text and visual are unchanged. The visual field description now notes explicitly that image_url parts bill at this rate; video_url input is no longer accepted (see below).
  • POST /v1/embeddings + POST /v1/embeddings/estimate. Any video_url content part returns 400 embeddings_video_unsupported (new error code). To embed visual content from a video, extract a representative frame in your pipeline and submit it as image_url; it bills at the visual rate.
  • Renamed error code. embeddings_video_too_many_parts (which previously fired for ≥ 2 video parts) was renamed to embeddings_video_unsupported and now fires for ≥ 1 video part. Update any integration that caught the old code on a single-video payload.
  • Response shape compatibility. POST /v1/embeddings/estimate retains tokens.video and breakdown.input.video on the response shape, both always 0, for one release cycle so existing SDKs that read them don’t break. Both fields will be dropped in a follow-up release.
This is a breaking change for any caller that pinned the embedding_pricing.video field or sent video_url parts. Embedding rates are explicitly mutable per the rate-card mutability note on /v1/models and /v1/chat/completions, so the change applies across all version pins. Zero customers were affected at release time.

2026-05-11

  • Image size presets reshaped. size now follows <tier>_<ratio> form: 2k_1_1, 2k_3_2, 2k_2_3, 2k_4_3, 2k_3_4, 2k_16_9, 2k_9_16, 2k_21_9, plus the same eight ratios at 4k_*. Sixteen presets total. The previous six names (square, landscape, portrait, hd_square, hd_landscape, hd_portrait) return 400 invalid_format.
  • Custom dimensions. width and height now require both, in [1024, 4096] per side, and are snapped server-side to multiples of 32. The response width/height reflect the post-snap value (may differ from the request by up to 31 px per side).
  • Mutual exclusion. Sending both size and width/height returns 400 parameter_invalid_combination. Sending only one of width/height returns 400 missing_field.

2026-05-15 (v1.0)

The first stable date-pin. Everything documented elsewhere on this site is what 2026-05-15 means.

Resource shape

  • /v1/images and /v1/videos are the create + read paths for image and video generations.
  • /v1/files is the upload path for reference images you reuse across generations.
  • /v1/webhook_endpoints registers + manages signed webhook deliveries.
  • /v1/loras and /v1/video_loras are the public catalog of styles.
  • /v1/team, /v1/balance, /v1/usage, /v1/usage/events cover account and metering. Per-model chat_pricing / embedding_pricing ships on GET /v1/models and reflects the caller’s effective rate including any per-team overrides.

Pricing

  • Image cost = image.base × count plus an optional enhance line when enhance_prompt: true. Refs and character_id are free — neither shifts the price.
  • Video cost = base_per_second × resolution_factor × duration_s (multiplicative). The breakdown carries the inputs; cost.amount is the product.
  • Team-level discounts surface as a discount_factor line in the breakdown when the team has a negotiated rate.

Webhook event types — v1.0 lineup

v1.0 ships eight event types. Four additional event types are reserved for a later date-pin — the underlying status transitions aren’t yet wired into the production code path, so they’re documented but never fire today. Currently fired:
  • image.completed / image.failed / image.cancelled
  • video.completed / video.failed / video.cancelled
  • usage.balance_low (per-team threshold; 1-hour debounce)
  • webhook.endpoint_disabled (auto-disable notification)
Reserved for a later date-pin (NOT fired today):
  • image.expired / video.expired — fires when a generation exceeds the 5-minute polling window without a terminal status. Requires a polling-timeout sweeper that flips status from processing to expired. Until then, stuck generations remain processing; the worker eventually fails them or the cancel endpoint resolves the hold.
  • image.moderation_rejected / video.moderation_rejected — moderation rejection currently throws 400 invalid_request from the create endpoint without inserting an inferences row, so there is nothing to fire a webhook against. Future change: insert the row in moderation_rejected state and fire the event.
If you subscribe with events: ["*"], the snapshot taken at registration time includes only the events that exist when you register. A future date-pin that adds *.expired or *.moderation_rejected will require you to update your registration explicitly — ["*"] does NOT auto-subscribe across date-pins.

Status enum

Generation status is one of: pending | processing | succeeded | failed | cancelled. expired and moderation_rejected are reserved enum values per the spec but never fire as wire values in 2026-05-15 (see “Webhook event types” above for the same reason).

Usage events — fields reserved for a later date-pin

GET /v1/usage/events returns line items with id, type, amount, currency, generation_id, hold_id, description, and created_at. Two fields commonly seen in similar ledger APIs (Stripe events, etc.) are intentionally NOT in 2026-05-15:
  • balance_before / balance_after — the team’s credit balance immediately before and after the event. Computing these accurately requires an authoritative balance-tracking column on usage_events (or a transactional bookkeeping query at write time). Reserved for a follow-up date-pin once the bookkeeping column is added.
If you need a per-event running balance today, sum amount across rows in chronological order with the type-derived sign (hold / charge / adjustment with negative description debit; release / refund / topup / positive adjustment credit).

2026-05-22

LLM pricing transparency redesign. Three breaking changes, one removal, one units change.

Model rename (breaking)

Four customer-facing slugs were renamed. Old slugs return 404 model_not_found.
Old slugNew slug
aurous-chat-proaurous-grow-2.0-pro
aurous-embed-visionaurous-embed-vision-1.0
Three Grow 2.0 chat models (aurous-grow-2.0-mini, aurous-grow-2.0-lite, aurous-grow-2.0-code) are unchanged but now share the family-wide 50% markup (previously 15%). No call-site change required.

/v1/pricing removed (breaking)

GET /v1/pricing now returns 404. Per-model rates are embedded directly in GET /v1/models under chat_pricing (chat models) and embedding_pricing (embedding models). One less round-trip; the data is identical and now lives alongside model metadata.

/v1/models response shape (breaking)

The model response gained two nullable siblings — chat_pricing and embedding_pricing — replacing the previous aurous_metadata.credits_per_1k_* fields. Per founder direction the unit is now per million tokens (credits_per_M), not per 1K. Important — 1000× scale change. Customers who hardcoded the previous credits_per_1k_* values into FinOps spreadsheets, monitoring dashboards, or rate-card exports must either (a) divide credits_per_M by 1000 to recover the per-1K number, or (b) update math to use per-million directly. New response shape:
{
  "id": "aurous-grow-2.0-pro",
  "kind": "chat",
  "display_name": "Aurous Grow 2.0 Pro",
  "chat_pricing": {
    "input":  { "credits_per_M": 75  },
    "output": { "credits_per_M": 450 }
  },
  "embedding_pricing": null
}
For embedding models, chat_pricing is null and embedding_pricing carries text / visual / video per-modality rates.

60-second jq recipe — migrate a FinOps script

If you were pulling aurous_metadata.credits_per_1k_input_tokens from /v1/models, the equivalent value lives at chat_pricing.input.credits_per_M / 1000:
curl -s -H "X-Api-Key: $AUROUS_KEY" https://api.aurous-labs.com/v1/models \
  | jq '.data
        | map(select(.kind == "chat"))
        | map({
            slug: .id,
            input_credits_per_1k:  (.chat_pricing.input.credits_per_M  / 1000),
            output_credits_per_1k: (.chat_pricing.output.credits_per_M / 1000)
          })'
For embedding models, swap chat_pricing.input/output for embedding_pricing.text/visual/video.

What didn’t change

  • Receipt shape on /v1/chat/completions and /v1/embeddings responses (usage, credits_charged, breakdown) is unchanged.
  • pricing_version in the receipt continues to snapshot the effective rate at hold time, so replays remain deterministic.
  • Image and video pricing on /v1/images, /v1/videos, /v1/loras, /v1/video_loras is unaffected by this release.
  • Aurous-Version pinning continues to work; chat and embedding rates intentionally track the most-recently published rate version (per spec — LLM provider economics shift on weekly cadence).