SStar Developers
模型目录、上传、任务和结果查看 Markdown

AI tasks, models, pricing, and results#

Discover capabilities#

For new integrations, load user-facing products from GET https://task.starhk.uk/v1/models?view=products&site_id=<SITE_ID> and effective pricing from GET /v1/pricing/rules?site_id=<SITE_ID>, using the user's bearer token where required. The flat GET /v1/models?site_id=... response remains only for backward compatibility. Do not show a provider selector.

Chat-only model pickers may use GET /v1/models?view=chat-picker&site_id=<SITE_ID>. It returns the same site-policy-filtered product contract but includes only task_type=chat modes, reducing first-load payload without creating a separate source of truth.

Render one card or selector entry per products[] item. After the user selects a mode, use that mode's exact task_model as the task model and its exact task_type as the task task_type. Never derive -t2v, -i2v, -r2v, -edit, or another child alias from product_id; the runtime mapping is authoritative. Use the selected mode's form_schema, capabilities, and reference_price, because different modes of the same product can have different inputs and prices. A callable parent can still contain unavailable modes, so disable any mode with callable=false and optionally explain unavailable_reason.

Model logo contract#

Star Task is the source of truth for model logos. An administrator maintains each model's Model Logo URL in Star Admin; frontend sites must consume the URL returned by the runtime catalog and must not bundle a vendor-to-logo table, infer a logo from family, product_id, or task_model, or construct an /applogo/... path.

  • Recommended product catalog (GET /v1/models?view=products&site_id=...): render
  • products[].icon on the product card and model selector. This is Star Task's product-view projection of the configured model logo/catalog icon.

  • Backward-compatible flat catalog (GET /v1/models?site_id=...): render each model's top-level
  • logo_url field. Do not read the duplicate value from inside capabilities.

  • Treat a missing or empty URL as “no logo” and show the site's neutral placeholder. Do not fall
  • back to a guessed vendor image. Use the returned URL verbatim after the frontend's normal http:/https: URL validation.

  • Use the model/product display_name as image alternative text. A logo update becomes visible
  • after the runtime catalog cache refresh, without a frontend release.

js
const productLogoUrl = product.icon; // view=products
const flatModelLogoUrl = model.logo_url; // backward-compatible flat view

Display model.reference_price.display_label beside each model so users see a unit-aware expectation such as 2点/张起, 12点/秒起, or separate input/output prices per million tokens. Use reference_price.details in a pricing popover or detail sheet. This value is explanatory only: after any billable option changes, call POST /v1/pricing/quote with the complete input and display its cost_points as the estimated total. Keep the legacy model-level cost_points only for backward compatibility; never present it as an unlabeled unit price. If reference_price.billing_mode is fallback, label it as a fallback rather than a normal selling price.

The site-scoped response is the maximum set the server currently allows for that site. With the default model_policy_mode=all, it contains the globally enabled runtime catalog; an optional administrator allowlist may narrow it further. The frontend may independently hide products or modes for its own UX. Compute the display set as the intersection of the fresh response and the site's display configuration; do not add entries from a global or hard-coded catalog. Remove locally cached entries when model_policy_version changes or an item disappears.

Prefer a remotely editable site display configuration containing only IDs, for example product_id values for whole products and task_model values for individual modes. Missing IDs are ignored. This lets a site expose 20 of 30 available models without changing Star Task or blocking the other models at the API layer. Use the server-side allowlist only when calls must actually be prohibited, not merely hidden from navigation.

Model metadata and availability are synchronized from RokoAPI and verified against the models callable by Star Task's server-side token. When a synchronized model has no local price, Star Task converts a safe structured RokoAPI USD price at 1 point = USD 0.0074 and publishes that initial default; media charges round up to whole points while text Token rates retain decimals. An existing global/site rule or administrator-adjusted price is never overwritten, and later upstream price changes are review signals rather than automatic repricing. Never infer a selling price from an upstream price list, copy a documentation snapshot into frontend code, or show a model that is absent from the runtime response. Frontend code uses only the Star alias and never chooses a provider.

For every catalog-synced product mode, honor availability, callable, priced, supported_modes, and form_schema from the runtime response. Render a model with callable=false as temporarily unavailable and never submit it. Build controls only from form_schema and enforce cross-field hints such as form_validation.at_least_one; do not infer streaming, reasoning, modalities, image limits, resolution, duration, format, or count from a model, family, or provider name. A model may have text, image, video, audio, and music capabilities at the same time, so do not treat model type as a single exclusive enum. When no structured form is supplied, show only the basic inputs that the runtime schema returns. Submit the flat field names returned by form_schema; Star Task maps any catalog-declared request_path such as metadata.lyrics before calling the upstream provider.

Each site may inherit Star Task pricing or use a site-specific rule configured by an administrator. Both modes are resolved server-side. The frontend must not submit a price, apply its own markup, or assume another site's rule. Use the site-scoped quote endpoint after option changes and the task creation response as the final charged amount.

An implementation should keep only identifiers in its display configuration and always render the current runtime object:

js
const catalog = await fetch(
  `https://task.starhk.uk/v1/models?view=products&site_id=${encodeURIComponent(SITE_ID)}`,
).then(response => response.json());

const selectedProducts = new Set(siteConfig.productIds ?? []);
const selectedModes = new Set(siteConfig.taskModels ?? []);
const showAllProducts = selectedProducts.size === 0 && selectedModes.size === 0;

const visibleProducts = catalog.products
  .filter(product => showAllProducts || selectedProducts.has(product.product_id) ||
    product.modes.some(mode => selectedModes.has(mode.task_model)))
  .map(product => ({
    ...product,
    modes: product.modes.filter(mode =>
      mode.callable === true &&
      (showAllProducts || selectedProducts.has(product.product_id) || selectedModes.has(mode.task_model))),
  }))
  .filter(product => product.modes.length > 0);

Sites that want to explain temporary outages may retain returned callable=false modes as disabled controls instead of filtering them out. They still must not submit those modes.

Image option contracts#

  • Read modes only from the returned product's modes and the selected mode's supported_modes. The recognized image modes are text-to-image,
  • image-to-image, reference-to-image, and image-edit; show only the modes returned for that model and submit the selected mode as task_type.

  • Build size, resolution, quality, count, and upload controls from form_schema. If the catalog
  • does not declare a field, do not reconstruct it from a model-name table or a remembered vendor contract.

  • Show image upload when the selected mode requires an input image or when runtime metadata
  • explicitly declares an image field. Send uploads through input.image_urls; use declared min_items / max_items when present and do not invent a fallback count.

  • Use the selected mode's exact task_model. Do not translate model names, endpoint types, or vendor-specific
  • speed/quality values in browser code.

Upload a local JPEG, PNG, or WEBP file, up to 24 MB, before quoting and creating the task:

js
const form = new FormData();
form.append('file', file);

const uploaded = await fetch(
  `https://task.starhk.uk/v1/upload?site_id=${encodeURIComponent(SITE_ID)}`,
  {
    method: 'POST',
    headers: { Authorization: `Bearer ${accessToken}` },
    body: form,
  },
).then(r => r.json());

Put uploaded.url in both the quote input and the final task's input.image_urls. Uploaded inputs live under the R2 uploads/images/ prefix and expire after two hours. They are temporary model inputs, not durable user assets. Star Task generation outputs use a separate durable prefix and are not subject to this lifecycle.

Video option and pricing contracts#

Video prices are usually per output second but may also depend on generation mode, resolution, quality, speed, or audio. Send duration in the field declared by form_schema, and send all other billable choices exactly as declared there. Always calculate the displayed total through POST /v1/pricing/quote; never copy a point-per-second table into frontend code. See [pricing.md](pricing.md) for the structured point rule contract.

Create and poll#

This section applies only to asynchronous image, video, audio, and music modes. Chat uses the separate synchronous/streaming contract in [chat.md](chat.md).

For an ordered ecommerce main-image or detail-image set, use the task collection contract in [task-collections.md](task-collections.md). Do not submit a browser-side loop of unrelated tasks; the collection API provides durable progress, partial resume, cancellation, and version history.

js
const idempotencyKey = crypto.randomUUID();
const created = await fetch('https://task.starhk.uk/v1/tasks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    site_id: SITE_ID,
    model: 'nano-banana-2',
    task_type: 'text-to-image',
    input: {
      prompt: 'A calm Hong Kong harbour at dawn',
      quality: '1K',
      image_urls: [uploaded.url], // Omit this field for text-to-image.
    },
    idempotency_key: idempotencyKey,
  }),
}).then(r => r.json());

const taskId = created.data.task_id;

Poll created.data.poll_url (or GET /v1/tasks/:id?site_id=...) about every 3–5 seconds. Stop at succeeded, failed, or cancelled; use a 15–20 minute UI timeout for long video/audio jobs without cancelling the server task automatically.

When a task reaches failed, display task.error in a modal, toast, or prominent inline error. Do not replace it with a generic failure string. When an upstream provider explicitly rejects a prompt under its content-safety policy, Star Task normalizes this field to a user-safe Chinese message asking the user to edit the prompt and retry. Other provider errors keep their existing behavior.

For successful audio/music tasks, use output.audio_url for an HTML audio player and download action, and use output.tracks when multiple results are present. The detail view should show the Star task ID, output.upstream_task_id, model, status, created_at, completed_at, cost_points, and error. Treat only Star Task output URLs as durable; upstream result links can expire. Star Task owns any required R2 transfer.

Charging guarantees#

  • Star Task resolves the site's effective price and coordinates point consumption/refund.
  • The create response contains authoritative cost_points.
  • reference_price is the unit-price display contract; /v1/pricing/quote is the parameterized estimate; task creation is the authoritative charge.
  • Refresh runtime model/pricing data when its pricing_version changes; a frontend release must not be required for an operations-side price update.
  • A rule imported from RokoAPI records source.expr_hash. It is an operations audit marker; frontend sites still calculate nothing locally and use the Star Task quote.
  • Reusing the same idempotency key for the same user action avoids duplicate tasks and duplicate charging.
  • A failed task follows Star Task's refund policy. Frontends must not call a point-consume endpoint themselves.

Result handling#

Render only Star Task output URLs. Image, video, and audio outputs from RokoAPI are copied to Star Task R2 storage before success is exposed. If persistence fails, the Roko task is failed/retried rather than reporting a temporary upstream link as durable.

Provider routing is internal. Omit options.provider; Star Task ignores legacy frontend provider overrides and prefers enabled RokoAPI routes globally, while models without one keep their current supplier. A RokoAPI-selected task never falls back to Evolink or GRSAI; RokoAPI performs its own channel routing. Disabled models and RokoAPI routes without a local selling price remain unavailable.