This guide verifies task video billing with model-level pricing tables.
/api/option/model_pricing./v1/videos.hailuo-video.seedance-2; for deterministic usage billing, point it at a mock upstream that returns usage.total_tokens.QuotaPerUnit = 500000 unless your environment overrides it.Set shell variables:
BASE_URL=http://127.0.0.1:3000
ADMIN_COOKIE='session=...'
API_TOKEN='sk-...'
Configure an exact per-call matrix:
curl -sS -X PUT "$BASE_URL/api/option/model_pricing/hailuo-video" \
-H "Cookie: $ADMIN_COOKIE" \
-H 'Content-Type: application/json' \
-d '{
"schema_version": 1,
"scope": "model",
"billing_unit": "per_call",
"preconsume_strategy": "exact",
"dimensions": [
{"key": "resolution", "source": "request.resolution", "type": "string", "default": null},
{"key": "duration", "source": "request.duration", "type": "number", "default": null}
],
"table": [
{"resolution": "768P", "duration": 10, "price": 0.04, "source": "manual"}
],
"fallback": {"strategy": "reject"}
}'
Submit a matched request:
curl -sS -X POST "$BASE_URL/v1/videos" \
-H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"model": "hailuo-video",
"prompt": "a pricing smoke test",
"resolution": "768P",
"duration": 10
}'
Expected quota:
actual_quota = price_usd * QuotaPerUnit * group_ratio
= 0.04 * 500000 * 1
= 20000
Submit an unsupported row and expect HTTP 400 with no quota change:
curl -i -X POST "$BASE_URL/v1/videos" \
-H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"model": "hailuo-video",
"prompt": "a pricing reject test",
"resolution": "1080P",
"duration": 10
}'
Configure a usage matrix:
curl -sS -X PUT "$BASE_URL/api/option/model_pricing/seedance-2" \
-H "Cookie: $ADMIN_COOKIE" \
-H 'Content-Type: application/json' \
-d '{
"schema_version": 1,
"scope": "model",
"billing_unit": "per_1m_tokens",
"preconsume_strategy": "minimum",
"dimensions": [
{"key": "resolution", "source": "request.resolution", "type": "string", "default": null}
],
"table": [
{"resolution": "720P", "price": 0.5, "source": "manual"}
],
"fallback": {"strategy": "reject"}
}'
Submit:
curl -sS -X POST "$BASE_URL/v1/videos" \
-H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"model": "seedance-2",
"prompt": "a usage pricing smoke test",
"resolution": "720P",
"duration": 5
}'
Fetch until complete:
TASK_ID=task_xxx
curl -sS "$BASE_URL/v1/videos/$TASK_ID" \
-H "Authorization: Bearer $API_TOKEN"
When the upstream completion response contains usage.total_tokens = 1000, expected final quota is:
actual_quota = total_tokens * token_unit_price_usd / 1_000_000 * QuotaPerUnit * group_ratio
= 1000 * 0.5 / 1_000_000 * 500000 * 1
= 250
The settlement must use the frozen token_unit_price_usd stored on the task billing context. Changing or deleting the current ModelPricingRules option after submit must not affect the completion calculation for that task.
Delete a matrix config:
curl -sS -X DELETE "$BASE_URL/api/option/model_pricing/hailuo-video" \
-H "Cookie: $ADMIN_COOKIE"
curl -sS -X DELETE "$BASE_URL/api/option/model_pricing/seedance-2" \
-H "Cookie: $ADMIN_COOKIE"
After deletion, requests for that model return to the legacy ModelPrice path. The ModelPrice option itself is not removed or modified by the model pricing table API.
The same flow can be run with:
"C:/Users/28221/.conda/envs/py312/python.exe" test-scripts/test_video_pricing.py
Required environment:
NEW_API_BASE_URL=http://127.0.0.1:3000
NEW_API_ADMIN_USERNAME=root
NEW_API_ADMIN_PASSWORD=123456
NEW_API_TOKEN=sk-...