Vault Billing & Packages API
A vault key carries three independent facts: how the credential arrived, how it bills, and which package it is on. This page is the API surface for the second and third of those — the fields you set to mark a key a flat-monthly subscription, and the catalogue you pick its package from.
For the dashboard walkthrough see Subscription keys & package tiers. For the vault itself see The Key Vault.
The three axes
Axis | Field | Values |
|---|---|---|
How it arrived |
|
|
How it bills |
|
|
Which package |
| a |
billing_mode is your override. Left at auto, the key's cost_type is derived from its provider (free, paid, subscription or unknown). Set to subscription or paid, your value wins.
The axes are independent, which is the point: an auth_type of api_key and a billing_mode of subscription is a valid, common combination — a MiniMax or Z.ai coding-plan key is pasted like an API key and bills like a subscription.
Base URL
https://spideriq.ai/api/v1All paths below are relative to that base.
Authentication
Authorization: Bearer <client_id>:<api_key>:<api_secret>
Authorization: Bearer spideriq_pat_…Reads require a member of the brand named in the path. Writes additionally require a brand admin (session) or a PAT carrying the opt-in gate:vault:write scope. A token that does not own {brand_id} gets 403; a key that belongs to another brand reads as 404, not 403. See Authentication.
Endpoint summary
GET /brands/{brand_id}/gate/subscription-tiers— the package cataloguePOST /brands/{brand_id}/integrations— add a key, with its billing axis setPATCH /brands/{brand_id}/integrations/{integration_id}— change the billing axis of an existing keyGET /brands/{brand_id}/integrations/{integration_id}— read the key back, including its meter
GET /brands/{brand_id}/gate/subscription-tiers
List the curated package catalogue. This is where tier_key values come from — there is no free-text tier.
provider— type string · optional · Filter to one provider's packages, e.g.minimax.
curl -s "https://spideriq.ai/api/v1/brands/14/gate/subscription-tiers?provider=minimax" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN"{
"tiers": [
{
"provider_name": "minimax",
"tier_key": "minimax_starter",
"label": "MiniMax Coding — Starter · $10/mo",
"price_usd_month": 10.0,
"window_hours": 5,
"window_limit": 500,
"weekly_cap": 10000,
"sort_order": 10
},
{
"provider_name": "minimax",
"tier_key": "minimax_plus",
"label": "MiniMax Coding — Plus · $30/mo",
"price_usd_month": 30.0,
"window_hours": 5,
"window_limit": 1000,
"weekly_cap": 20000,
"sort_order": 20
},
{
"provider_name": "minimax",
"tier_key": "minimax_max",
"label": "MiniMax Coding — Max · $50/mo",
"price_usd_month": 50.0,
"window_hours": 5,
"window_limit": 2000,
"weekly_cap": 40000,
"sort_order": 30
}
]
}window_hours and window_limit are the two halves of the meter: the length of the rolling window, and how many requests the plan allows inside it. weekly_cap is present only where the plan has a weekly ceiling; it is null otherwise. price_usd_month is null for a plan with no published price.
The catalogue is small and curated on purpose — 14 packages across 6 providers (anthropic, codex, gemini_cli, minimax, zhipu, qwen) as of 10 August 2026. Read it rather than hard-coding a tier_key; plans get renamed and retired.
Note: this route is fail-soft. If the catalogue cannot be read it returns 200 with
{"tiers": []}rather than an error, so the key editor still opens. An empty list means "no catalogue available", not "this provider sells no plans".
Setting the billing axis on a key
Both the create and the update path take the same two fields.
billing_mode— type string ·auto·subscription·paidsubscription_tier— type string · atier_keyfrom the catalogue
curl -s -X PATCH "https://spideriq.ai/api/v1/brands/14/integrations/42" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"billing_mode": "subscription", "subscription_tier": "minimax_max"}'Setting subscription_tier copies that package's window_hours and window_limit onto the key as sub_window_hours and sub_window_limit. That is what gives the capacity meter a denominator. Change the package later and the window is re-seeded from the new one.
subscription_tier is a soft reference, not a foreign key. A tier_key the catalogue does not contain is accepted and stored, and the window is left unset — the request succeeds, the meter stays blank, and a warning is logged. Read the catalogue first and this cannot happen.
A subscription key is never pooled
A key whose billing_mode is subscription or paid cannot be shared into the pool. Sending both in one request is rejected:
{
"detail": "A key marked billing_mode='subscription' is private to your brand and cannot be shared with the pool."
}422 Unprocessable Entity. The rule is also enforced in the database, so a key cannot end up pooled by any other path either. The API returns the error rather than silently un-ticking the box you just ticked.
cost_type: free keys are unaffected and still pool normally.
Reading the meter
GET /brands/{brand_id}/integrations/{integration_id} returns the billing axis and the meter together:
Field | Meaning |
|---|---|
|
|
| the override itself, |
| the package key, or |
| window length copied from the package |
| allowance copied from the package — the denominator |
| usage so far inside the current window — the numerator |
| when the window rolls |
|
|
sub_window_percent is null until a package is set, because until then there is no denominator to divide by. A blank meter means "no package chosen", never "no usage".
CLI
# discover the packages
spideriq gate subscription-tiers --brand 14 --provider minimax
# set the billing axis and the package together
spideriq gate keys update 42 \
--billing-mode subscription \
--subscription-tier minimax_maxMCP
get_subscription_tiers— the cataloguecreate_brand_integration— add a key withbilling_mode+subscription_tierupdate_brand_integration— change them on an existing keygate_key_update— the same change from the admin surface
Errors
Status | When |
|---|---|
400 |
|
403 | the token does not own |
404 | the key exists but belongs to another brand |
422 |
|
See Errors for the full response shape.