Token packages and multimodal API
The Token API provides package queries and purchases, payment recovery, allowance and usage queries, and multimodal model calls. White-label customers can complete these operations in their own products without first visiting the platform Console.
User authorization
Request the published Token API Product under API and permissions → User identity. Configure login callbacks and use Authorization Code with PKCE and current user consent. The user access token must belong to that application's user OAuth Client.
| Operation | Minimum Scope | Customer authority |
|---|---|---|
| Catalog | commerce.catalog.read | Current commercial read access |
| Orders | commerce.order.read | Current commercial read access |
| Purchase and checkout | commerce.checkout.create | Current payer authority |
| Models | inference.models.read | Current product consent |
| Inference | inference.invoke | Current product consent and eligible allowance |
| Balance | inference.balance.read | Current account billing read access |
| Usage | inference.usage.read | Current account billing read access |
After automatic configuration, confirm that the actual binding is bound, then obtain a fresh PKCE user token with the minimum scopes needed for the operation. Audiences are issued through active products and permissions; customers do not add internal audiences manually. Drifted configuration or a token issued before configuration was enabled may be rejected.
Inference users do not need payer authority. Payment, allowance arrival and API authorization are independent states. User tokens, application identity tokens and model API keys cannot be exchanged for one another.
After authentication, call /open-platform/v1/delegated-grants with the current application's user OAuth Client token to save product consent.
application_id,environmentandapi_product_id: use the stable application ID, an explicitsandbox|productionenvironment and the API product.scopes: include only the permissions needed for this operation.- Resource scope: use
{"resource_type":"token_product","resource_ids":["<product_code>"]}.
Save the returned Grant ID for subsequent calls. Revoked or expired consent causes calls to be rejected. See User authorization for creation and revocation parameters.
Use the current environment's GOODVISION_API_BASE and include the following headers in every request. Select sandbox|production explicitly. The platform derives the Client, binding and Scope; requests do not accept prices, billing accounts or execution endpoints.
Authorization: Bearer ${GOODVISION_USER_ACCESS_TOKEN}
X-GV-Organization-ID: ${GOODVISION_CUSTOMER_ORGANIZATION_ID}
X-GV-Application-ID: ${GOODVISION_APPLICATION_ID}
X-GV-Environment: ${GOODVISION_APPLICATION_ENVIRONMENT}
X-GV-API-Product-ID: ${GOODVISION_API_PRODUCT_ID}
X-GV-Delegated-Grant-ID: ${GOODVISION_DELEGATED_GRANT_ID}
X-GV-Product-Code: ${GOODVISION_PRODUCT_CODE}The platform verifies the application, consent and product scope selected by these headers. The same application uses separate runtime identities, consent, orders and allowance in Sandbox and Production.
Purchase and original checkout recovery
| Endpoint | Purpose |
|---|---|
GET /open-platform/v1/token-packages | Read current offers, prices, Credits conversion, validity, eligibility, model rates and terms |
POST /open-platform/v1/token-orders | Create an order for the selected package version and terms |
GET /open-platform/v1/token-orders | Current customer and application orders |
GET /open-platform/v1/token-orders/{id} | Recover the original order and payment state |
POST /open-platform/v1/token-orders/{id}:checkout | Create or recover that order's original hosted checkout |
Send a stable Idempotency-Key when creating an order:
{"package_id":"<catalog.package.id>","package_version":3,"accepted_terms_sha256":"<catalog.package.terms_sha256>"}Purchase and payment take two steps:
- Save the Order ID returned by order creation.
- Call the order's
:checkoutendpoint with the original payment operation key and opencheckout_url. - After payment, query the original order. Only
status=paidconfirms payment. - Call the balance API separately to verify allowance arrival.
Check state after the customer returns before displaying payment success.
For an in-app purchase, add return_reference: "application-entry" when creating the order. Success and cancellation return to the application's reviewed published HTTPS entry with payment, payment_order, organization, application, environment and product. Do not send an arbitrary return URL. Later address changes preserve the original order's destination. Return parameters only locate the order; payment=success cannot replace a paid receipt from GET /open-platform/v1/token-orders/{id}. Use bounded automatic reads while awaiting confirmation and offer manual reads after an error or deadline. Read the balance separately after payment confirmation. SaaSdemo prepares payment for that same order without another purchase or sign-in.
After a timeout or lost response, keep the original order, body and key. Continue querying and recovering that request to avoid creating another order or payment.
Changed package versions or terms return 409. Read the catalog again and ask the user to confirm. If the returned package version, terms hash or order differs from the original operation, retain the original content and key and continue recovery. Confirm before displaying success.
Credits add-on policies
Add-ons are one-time purchases with no automatic renewal. When a package declares units_per_credit, divide units by that ratio to display Credits. Keep historical Token units unchanged and use the ratio declared by the original package.
The response returns exactly one of validity_days or validity_months:
- Days: each day is 24 hours.
- Calendar months: count from confirmed payment in UTC. If the target month has no matching date, use its last day, for example January 31 to February 28.
After allowance arrives, use the original batch's expires_at. Delayed callbacks and new package versions do not extend expiry.
subscription_requirement can specify eligible purchased plan_codes; allow_free defaults to false. Use the catalog's eligibility.eligible to enable a new purchase. reason explains the result:
| Reason | Meaning |
|---|---|
unrestricted | No subscription restriction |
eligible_subscription | The current subscription qualifies |
subscription_required | A qualifying subscription is required |
Show ineligible packages with a prompt to activate or renew a qualifying plan. Names, trial status and pending upgrades cannot determine eligibility. Scheduled cancellation remains effective until the actual deadline.
Ineligible new purchases return 403 and token_customer_denied. Read the catalog to distinguish missing subscription eligibility from denied customer access. Already accepted orders and their original checkout can still be recovered after new-purchase eligibility ends.
Use the original order's refund_policy:
| Value | Rule |
|---|---|
none | No refund |
unused | Only an entirely unused package without pending reservations can be refunded through an authorized operator workflow |
Historical orders without this field retain the original whole-unused rule. Display the policy accepted at purchase.
Models and inference
GET /open-platform/v1/inference/models returns currently executable models with eligible allowance. Each model's x_gv.execution_profiles lists executable protocol, input and limit combinations, for example:
{"protocol":"openai_chat","input_modalities":["text","image"],"context_limit":32768,"output_limit":4096,"supports_tools":false}Select one x_gv.execution_profiles entry that satisfies the protocol, input modalities and limits. Do not combine capabilities from different entries. openai_chat, openai_responses and anthropic_messages map to the three endpoints below.
Image, audio and file inputs require a declared native protocol. Undeclared media is rejected before allowance reservation. Models with unknown limits are excluded from the catalog. Every call rechecks current authorization, allowance and model state.
This release returns text and supports explicitly declared caller-executed function tools. Audio output, video input, built-in metered tools, standalone image/video generation, background execution and saved response state are unavailable. Responses requests must include their complete context, set store and background to false if supplied, and omit previous_response_id.
POST /open-platform/v1/inference/chat/completions
POST /open-platform/v1/inference/responses
POST /open-platform/v1/inference/messagesSpecify a model, a fixed Idempotency-Key and a positive integer output limit:
| Protocol | Output limit parameter |
|---|---|
| Chat | max_completion_tokens or max_tokens |
| Responses | max_output_tokens |
| Messages | max_tokens |
Each request supports one output. The model must support the chosen input modalities and protocol.
{"model":"<eligible_model_id>","max_completion_tokens":1024,"stream":true,"messages":[{"role":"user","content":[{"type":"text","text":"Describe this image"},{"type":"image_url","image_url":{"url":"https://assets.example.test/example.png"}}]}]}Streaming responses use text/event-stream. Save the response header X-GV-Inference-Request-ID to look up the usage record's request_id.
Each logical request key executes at most once. Repeating it returns 409 without consuming allowance again. Timeouts, interrupted streams or missing final usage leave the reservation pending review. Query the original request rather than repeating it with a new key.
Before a call, the platform reserves allowance using the model's conservative input limit and the requested output limit. Once the result is known, it settles actual input and output Tokens at the purchased rates and releases the difference.
Rates are stored as integer millionths. Consumption is ceil((input_tokens × input_weight_micros + output_tokens × output_weight_micros) / 1000000). Raw Token usage and package consumption are returned separately.
Balance, usage and recovery
GET /open-platform/v1/token-balance returns available, reserved, consumed, expired and revoked units, with at most 100 grants. Pass next_grant_cursor as grant_cursor for the next page.
Read ledger_unit on offers, batches, balances and usage. usd_micros_v1 means one millionth of USD per unit: 10000001 is USD 10.000001. An absent unit retains the historical weighted-Token or explicit Credits conversion; never infer USD. Allowance and purchase price are separate. A scope cannot mix denominations or convert its historical allowance.
USD model prices freeze usd_price_version and integer input_usd_per_million_micros / output_usd_per_million_micros, the micro-USD prices per million input / output Tokens. Weight fields are zero. Consumption is ceil((input_tokens × input_price + output_tokens × output_price) / 1000000), rounded once for the complete request and returned in micro-USD. Keep sub-cent precision in displays and exports; never label the raw integer as Tokens or whole dollars.
Allowance batches
Purchased allowance appears in grants; commercial benefits and subscription-period allowance appear in benefit_grants. Both arrays share the 100-item page limit and cursor. Totals include both kinds of issued batches.
A benefit's benefit.source_type can be welcome, subscription, activity or campaign, with source, policy version, period and expiry. These values identify an issued batch; check policy availability separately. An empty or absent benefit_grants array also does not establish policy availability.
blocked=true stops new reservations for that batch. Existing requests still settle or release their original allocations. Usage allocations retain references such as source_type and policy_id; order_id and package_id may be null. Benefits do not represent purchases or payments and do not create orders. USD denomination is the spendable allowance's face value, not paid revenue or a refundable amount.
Read usage records
GET /open-platform/v1/token-usage?limit=50 returns records and next_cursor. Pass it as cursor for the next page. Each page reflects state at query time; refresh from the first page.
| State | Meaning |
|---|---|
reserved | The request is in progress and allowance is reserved |
pending_review | The result awaits verification |
settled | Consumption has been settled |
released | Zero consumption was confirmed and the reservation released |
Filter and summarize usage
Use offset=0&limit=50 for paged statistics. Optional filters are from, to (ISO 8601 timestamps, inclusive start and exclusive end), model, status, package_id, order_id and grant_id (purchased batch). This mode cannot use cursor or an exact request lookup.
The response's page, summary, models, regions, trend, trend_granularity and packages cover all matching records. Trends cover the full UTC query period:
| Granularity | Range |
|---|---|
granularity=auto | Hourly through seven days, daily through 366 days, then monthly |
hour | Requires a start; at most 31 days |
day | At most 366 days |
Keep filters unchanged between pages. Refresh to read current records.
Statistics fields:
| Field | Meaning |
|---|---|
summary.requests | Logical requests, including settled and unresolved requests |
settled_requests, released_requests, review_requests | Counts of settled, released and pending-review requests |
reserved_units | Allowance still reserved by matching requests |
consumed | Actual deduction at purchased model rates; cached input is included in input Tokens |
allocations | Each request's package version, original order, batch, expiry and deduction or reservation |
packages | Actual deduction grouped by package version |
One request may use multiple packages, so grouped request counts overlap and cannot be added. Package filters retain every allocation and the full deduction of matching requests for verification. Raw Tokens are not estimated across packages. Package allowance is not a monetary amount.
To check one logical invocation, use its response header:
GET /open-platform/v1/token-usage?request_id=<X-GV-Inference-Request-ID>An exact lookup returns zero or one record for the current customer, application, environment, product and billing account. It cannot include cursor or limit.
settled: consumption was deducted.released: zero consumption was confirmed.reservedorpending_review: continue waiting or checking.
An empty result means no record is currently readable. It does not prove zero upstream consumption or permit another call with a new key. Lookup requires inference.usage.read and billing read access; ordinary inference permissions do not include billing access.
| Status | Action |
|---|---|
401/403 | Check sign-in, the application user identity, API scopes, consent and customer access |
402 | Check allowance, expiry and pending-review requests |
409 | Query the original order or request and retain its key; confirm changed purchase conditions |
422 | Correct purchase parameters, model, input capabilities, output limits or pagination |
429 | Wait for Retry-After and retain the original key |
503 | Keep the original order and key; query state before recovery |
Availability follows the API Product and current Application permission state. This guide does not imply activation in a particular environment.
Customer space and model privileges
Resolve the customer space through user context; users do not enter private IDs. Personal-space entry or cross-Application correlation grants no model scopes, consent or credits. Verify those permissions separately as described here.