tokenlab-run
The execution contract for every TokenLab media and decision call: read the model contract, pick the operation, estimate cost, upload or link inputs, call the endpoint, wait for async tasks, and read
Files5
View on GitHubSKILL.mdskills/tokenlab-run/SKILL.md
GitHubTokenLab Run
Run one TokenLab request correctly: right model, right operation, right fields, a known price, and a finished result. Every outcome skill in this repository uses this procedure.
Roots and auth
- API root:
https://api.tokenlab.sh. Docs:https://tokenlab.sh/docs. - Auth:
Authorization: Bearer $TOKENLAB_API_KEY. Read the key from the environment. Never print it, log it, or put it in a URL. - Model discovery and pricing need no key. Every create, upload, poll, and cancel call needs a key.
Execution surfaces
| Surface | When | Notes |
|---|---|---|
| HTTP | Default for scripts and apps | Use the helper below or plain curl / fetch / requests |
| MCP | The client has the TokenLab MCP server | core profile has list_models, get_model, get_model_pricing, create_image, edit_image, create_video, create_music, create_3d_model, create_speech, transcribe_audio, upload_file, get_task_status, cancel_task, evaluate_decisions. World tools (create_world, get_world_status) need the full profile. |
| SDK | The app already uses the OpenAI SDK | Base URL https://api.tokenlab.sh/v1. SDKs cover images and audio. Use HTTP for video, music, 3D, worlds, and System One. |
Helper script, standard library only:
python scripts/tokenlab_run.py contract MODEL --operation OP # step 1-2
python scripts/tokenlab_run.py price MODEL # step 3
python scripts/tokenlab_run.py run /v1/videos/generations --json @body.json --wait # step 5-7
python scripts/tokenlab_run.py poll TASK_ID_OR_POLL_URL # resume a stored task
The path is relative to this skill's folder. Other TokenLab skills call it as ../tokenlab-run/scripts/tokenlab_run.py. Without the helper, send the same requests with curl (see references/recipes.md).
run prints the task identity (request_id, task_id, poll_url) to stderr as soon as the create call returns. --wait waits up to 100 s by default. Exit code 0 means a terminal success, 1 means failed or unknown, and 2 means the task is still running: continue with the resume command in the output.
The procedure
- Read the model contract.
GET /v1/models/{model}. Confirmtokenlab.lifecycle.stageisactive. Readtokenlab.public_contract_summary(orpublic_contract):public_operations: the operations this model sells.request_endpoint_by_operation: the endpoint for each operation. It wins over any table in a skill. For example, many image-edit models use/v1/images/generationswithoperation: "image-edit", not/v1/images/edits.operation_constraints[]: per operationsupported_parameters,allowed_durations,allowed_resolutions,allowed_aspect_ratios,parameter_options, andnotes.recommended_request/recommended_request_summary: a known-good starting body.tokenlab.deliveryAvailability.operations[op]: which delivery options (verified,official) have supply for that operation.
- Pick the operation and build the body. Send
modelalways. Sendoperationexplicitly when the endpoint takes it (images, video). Do not sendoperationto/v1/3d/generations; it infers text-to-3d or image-to-3d from the inputs. Send only fields insupported_parameters, with values from the allowed lists. A field that is not listed returns400 unsupported_parameter; remove it or pick another model. Do not guess fields from the model name. - Estimate the cost first. TokenLab has no dry-run. Read
GET /v1/models/{model}/pricing. Multiply the price by your quantity (images, seconds, characters, tokens, or requests;pricing_unittells you which). Prices sit inpricing_detailsasentries,formulas,unitPriceVariants, or a credit table, plusminimumUnitCountwhere a minimum applies.officialis the Official price;platformis the Verified price. The default delivery optionAutoholds the higher amount and charges the route that ran. To force one option, sendX-TokenLab-Delivery-Policy: verifiedorofficial(helper:--delivery); with no supply in that option the request fails and is not charged. Use the Official price as the upper bound. Tell the user the estimate before a paid video, 3D, or world job, and before any batch. - Provide input media.
- Remote inputs must be public
httpsURLs that stay valid until the task starts. No private hosts, credentials, fragments, or short-lived signed URLs. - A TokenLab result URL from an earlier task (
https://api.tokenlab.sh/v1/media-results/...) is a valid input. Chain steps this way: generate an image, then animate or edit that URL. - Many image and video fields also take a
data:URL, but media URL fields accept at most 8192 characters. That fits a small thumbnail, not a photo or an audio clip. Host larger private files at a publichttpsURL instead. POST /v1/files(purpose=user_data, optionalmodel) returns afile_idfor/v1/images/editsimages[].file_id. It is not a general media host for video, music, or 3D.- Speech-to-text takes a multipart
fileupload (max 25 MB).
- Remote inputs must be public
- Call the endpoint. Save the
x-request-idresponse header, the returnedid/task_id, model, and your own job ID before you do anything else. - Wait for async results. Video, music, 3D, and worlds are always async. Images and transcriptions can be sync or async; decide from the response, not from the model. A response with
status: "pending"or"processing"is a task:- Poll
GET /v1/tasks/{id}every 5–10 s. It serves every task type. Stop atcompletedorfailed. - A status read returns HTTP 200 even when the task failed. Decide from
status. On failure readerror_details(code,param,message,retryable).paramnames the field to fix. - A timeout on your side is not a failure. Keep the task ID and resume polling. Never create a second task because a poll failed or a page refreshed.
- Cancel only on user request:
DELETE /v1/tasks/{id}. Only some queued tasks can be cancelled (400 unsupported_task_cancel,409 task_not_cancellableotherwise).
- Poll
- Read the result. Images:
data[].url(orb64_jsonon a sync request). Video:video_url,video.url, orvideos[]. Music:audio_url(plusvideo_url,image_url,lyricsfor some models). 3D:model_urland format URLs such asglb_url. Worlds:world_marble_url,glb_url,pano_url. TTS returns audio bytes. Result URLs stay valid for 30 days; download anything the user needs for longer. Downloads redirect, so follow redirects. A URL can return502 media_unavailablefor about a minute right after the task completes; wait and try the download again. Do not handstream_audio_urlto the user; it is a temporary listening link, not the result.
Errors
| Error | Meaning | Action |
|---|---|---|
400 unsupported_parameter / invalid_request with param |
Field not in this model's contract | Fix that field from operation_constraints; do not drop the user's core input |
400 model_not_found + did_you_mean |
Wrong or retired ID | Re-discover; switch only with user consent |
402 insufficient_balance |
Not enough balance; estimated_cost_usd shows the need |
Tell the user. Do not switch to a cheaper model without consent |
429 |
Rate limit | Wait Retry-After / retry_after, then retry the same request |
| Create request timed out or the connection broke | The task may exist and may be charged | Do not resend. Ask the user first, and check Runs or Usage in the console. The helper reports accepted: unknown |
5xx on a create request |
The request may or may not have started | Retry only when the body says retryable: true and no task ID came back; otherwise ask the user |
503 all_channels_failed / delivery_tier_unavailable with retryable: false |
No supply for this operation and delivery option | Do not repeat. Pick another model that publishes the operation |
Task failed with error_details.retryable: true |
Transient upstream failure | One new task is acceptable; it is a new charge |
Retrying a failed generation creates a new task and a new charge. Ask before you retry paid video, 3D, or world jobs.
Quality bar
- The body uses only contract fields, and the model publishes the operation.
- The user saw a cost estimate before any paid job above a few cents.
- The task ID was stored before polling, and the final answer names the result URL, the model, and the task ID.
- Failures report
error_details.codeandparam, not only "it failed".
References
references/recipes.md: copy-ready HTTP bodies for each endpoint family.scripts/tokenlab_run.py: contract, price, run, poll, cancel, and upload commands.
Related skills
tokenlab-model-picker: choose the model before you run it.tokenlab-prompting: write the prompt for the chosen model family.tokenlab-api-integration: put the same flow into application code.