# Runtime model availability and point pricing

Star Task periodically imports RokoAPI's public model catalog and separately verifies the models callable by its server-side RokoAPI token. Frontend sites must consume Star Task's effective runtime contract; they must not fetch RokoAPI directly.

## Model availability

Load `GET /v1/models?view=products&site_id=<SITE_ID>`. This is the current server-allowed runtime set. A site may choose a local or CMS-managed display subset, but every displayed item must still come from this response.

- `callable=true` is required before task submission.
- `availability=temporarily_unavailable` disables submission while preserving product history.
- `unavailable_reason` explains an upstream disablement, missing local point price, or disabled route.
- Use each mode's exact `task_model`, `task_type`, `form_schema`, and `form_validation`.
- Do not infer a new model, mode, limit, or alias from a model family name.

Global model enablement, route state, upstream availability, and published prices can change without a frontend release. Re-fetch the catalog on page entry and after a stale-cache/focus boundary; the endpoint currently advertises a short cache window. Remove a configured item when it disappears from the runtime response. A local display selection is a UX choice, not a permission boundary: use an administrator-managed Star Task `allowlist` only when the model must also be rejected server-side.

Star Task keeps the last successful upstream snapshot when synchronization fails. A transient catalog request must therefore not make every frontend model disappear.

## Point pricing

RokoAPI's public `pricing_display` is an upstream USD reference. On first synchronization, Star Task automatically converts a model with no local price at `1 point = USD 0.0074` (`135.135135... points/USD`) and publishes the result as its editable initial price. The frontend uses only the Star Task point rule.

For legacy image, video, audio, and music rules, Star Task preserves the structured pricing dimensions and rounds the final task charge upward to a whole point. Rules that explicitly declare `point_increment: 0.01` and fixed AI-tool prices can charge in 0.01-point increments. For text models, input, output, and recognized cache-read USD rates are converted into per-million-Token point rates and retain decimals; the normal model-family minimum charge still applies during settlement. A missing, malformed, actual-usage-only, or unsupported upstream price is never guessed, so that model remains unavailable until an administrator supplies a safe local price.

The supported runtime conditions include resolution, quality, speed, generation type, output seconds, output count, input image count, input seconds, and audio selection. A structured rule may contain:

```json
{
  "source": {
    "provider": "rokoapi",
    "model_name": "vidu-q3-turbo",
    "expr_hash": "upstream-price-version",
    "currency": "USD",
    "points_per_usd": 100
  },
  "rounding": "ceil",
  "rate_table": {
    "basis": "duration",
    "rates": [
      {
        "when": { "generation_type": "text-to-video", "resolution": "720p" },
        "points_per_unit": 8,
        "unit": "second"
      }
    ]
  }
}
```

The `source` object is an audit/version marker. It is not a browser-side conversion instruction. Administrators can change point values and margins after creating a draft. By default, upstream `expr_hash` changes do not replace published point prices. Only a global rule explicitly published with `source.update_mode: "follow"` is regenerated during catalog sync; site overrides remain untouched.

## Automatic initial price and administrator overrides

The automatic path is deliberately insert-only:

1. Synchronize the RokoAPI catalog and create the model/mode bindings.
2. If an exact binding has no local price, convert the structured USD price with the fixed default ratio.
3. Publish that initial global price and enable the route in the same synchronization batch.
4. If any global rule, site rule, default cost, or text Token price already exists, preserve it.

Administrators can later edit a global or site-specific price through Star Admin. Authorized site backends can publish their own site prices through the delegated API below. Synchronization preserves manual and historical rules. Explicitly opted-in global `follow` rules are the exception; site overrides remain independent. If the upstream `expr_hash` changes, the current point price stays live and the change is recorded for review. The existing draft/confirm endpoints remain available for an administrator who wants to recalculate and explicitly republish an exact model.

Automatic publication supports finite media `rates`/`modifiers` and text `token_rates` containing recognizable input and output rates. Other actual-usage contracts remain manual.

## Frontend display and quoting

1. Show `reference_price.display_label` and `reference_price.details` as the current user-facing unit price.
2. Call `POST /v1/pricing/quote` after any billable parameter changes.
3. Show the returned `cost_points` as the estimate and its `breakdown` as an optional explanation.
4. Treat task creation's `cost_points` as the authoritative charge.
5. Refresh cached models/rules when `model_policy_version` or `pricing_version` changes.

Treat point values as numbers in application state. Public debit and price-configuration APIs accept 0.01-point increments; internal actual-usage settlement may retain up to three decimal places. Format every end-user balance, quote, charge, and refund with exactly two decimal places. Never round a value before submitting it back to Star Task or Star Auth; display rounding is presentation-only.

The UI may filter by `product_id` to hide an entire product or by `modes[].task_model` to expose only selected modes. End-user rendering must always join those IDs back to fresh runtime prices, names, schemas, and availability. A site administration UI may store a desired price draft, but must publish it through the delegated API before treating it as live.

Never parse or execute `billing_expr`, multiply USD prices in the browser, hard-code price tables, or send a caller-calculated price with a task request. Unsupported actual-usage contracts require a manually published Star Task rule.

## Site self-service pricing (recommended)

After a one-time authorization, each site's trusted backend can manage its own prices without asking the platform administrator to make each change. The site gets a dedicated pricing token, not the platform admin secret or an ordinary site API key.

**Read [the complete self-service pricing contract](site-pricing.md)** for provisioning, endpoints, a server-side example, conflict handling, rollback and rollout instructions.

Use `https://task.starhk.uk/site-api/v1/pricing`. Site identity comes exclusively from the token; omit `site_id` and `X-Site-Id`. `GET /models/<TASK_MODEL>` returns the current `etag`. A publish request is:

```http
PUT /site-api/v1/pricing/models/<TASK_MODEL>
Authorization: Bearer <SITE_PRICING_TOKEN>
Content-Type: application/json

{
  "expected_etag": "<etag from GET>",
  "pricing": {
    "type": "image_resolution",
    "field": "resolution",
    "prices": { "1K": 3, "2K": 4, "4K": 6 }
  }
}
```

A fixed price is `{"type":"fixed","points":3}`; restore inheritance with `{"type":"inherit"}`. These are complete replacements. Image prices are per image, multiplied by `n`; other fixed media prices are per task. The initial delegated API does not support chat Token pricing, arbitrary expressions, or provider-controlled billing. Those remain platform-admin operations.

## Platform administrator price management

In Star Admin, open **站点管理 → 模型定价**, select the exact model and generation mode, then edit the complete effective rule. For image resolution pricing, expand **按图片分辨率填写价格**, select the parameter used by the model (`resolution` or `quality`), enter the per-image points, generate the rule, and save. Generating a rule does not publish it. **恢复全局价格** deletes only this site's override.

The authenticated Star Auth admin API is:

```http
GET /admin/sites/<SITE_ID>/task-model-policy
PUT /admin/sites/<SITE_ID>/task-models/<TASK_MODEL>/pricing
Authorization: Bearer <STAR_ADMIN_SESSION_TOKEN>
Content-Type: application/json
```

The GET response includes `pricing` (site overrides) and `effective_pricing` (site/global merged rules, including `source_site_id`). Calls use the Star Admin host and administrator session, not a frontend user's login or site API key.

Trusted server-side administration can instead call Star Task directly:

```http
PUT /internal/admin/sites/<SITE_ID>/models/<TASK_MODEL>/pricing
Authorization: Bearer <TASK_ADMIN_SECRET>
Content-Type: application/json
```

Example: 1K = 3 points, 2K = 4 points, 4K = 6 points per image, when the selected mode uses `resolution`:

```json
{
  "mode": "custom",
  "task_type": "text-to-image",
  "rules_json": {
    "currency": "points",
    "default_cost": 3,
    "rounding": "ceil",
    "quantity": { "field": "n", "default": 1, "min": 1 },
    "dimensions": {
      "tier": {
        "field": "resolution",
        "values": { "1K": 3, "2K": 4, "4K": 6 }
      }
    }
  }
}
```

Use the runtime mode's exact `task_model`, `task_type`, resolution field and supported values; do not infer the model ID from a product name such as GPT Image 2.5. Configure each distinct mode/model binding separately. The example replaces the entire rule (including any previous quality surcharges or modifiers); it is not a partial merge. `n=2` doubles the per-image charge. Models with other output-count fields need a corresponding quantity rule.

To restore inheritance, PUT `{"mode":"inherit","task_type":"text-to-image"}` to the same endpoint. Saving a custom rule increments its pricing version. After saving, re-fetch the site catalog/rules and verify all three resolutions with `POST /v1/pricing/quote`; task creation remains authoritative. Existing tasks keep their recorded charges. Other sites and global prices are unchanged.

Never embed administrator credentials in a frontend bundle. Site integration tools may use an explicitly authorized server-side pricing token. Without that token or administrator access they should request one-time authorization; they must not substitute hard-coded display prices for publication.

## Image resolution pricing v1

See [the complete image pricing contract](/docs/image-resolution-pricing/) for 1K/2K/4K, defaults, legacy quality aliases and exact pixel mappings. New rules opt in with `input_contract.version=1`; delegated site publication uses `pricing.contract_version=1`. Existing rules and callers stay compatible.

`POST /v1/pricing/quote` additionally returns `pricing_revision` and `normalized_input` for strict image rules. New callers should send that revision as `options.pricing_revision` to `POST /v1/tasks`; a stale revision returns 409 `PRICING_CONFLICT` before charging. Legacy callers may omit it. SDK: `client.quoteTask(...)`. Never use numeric `pricing_version` as a quote lock.
