STOP WASTING PAID TOKENS. START POOLING ACCOUNTS TODAY. [ GET YOUR VAULT ]

Your Subscriptions

Your brand's subscriptions are the LLM plans and credentials it has in the vault — a MiniMax package, a Claude Max seat, a pay-as-you-go OpenAI key. GET /api/gate/v1/subscriptions tells you which of them you can actually use right now, and which concrete model ids you may pin.

This is a different question from "what models exist?". The model catalog lists everything SpiderGate can route to, for everybody — over a thousand rows. This page is about the much shorter list your own brand may complete on today.

Who this is for

You, if something on your side chooses the model — a build runner, an orchestrator, a planner that decides (subscription, model) per job, or a script that needs to size how many jobs it can run in parallel.

If you send model: "spideriq/coding" and let the gateway route for you, you do not need this page. That is the point of a task alias: the routing decision is ours. Read on when you want to make that decision yourself.

What this does

For every subscription your brand holds, it answers four things:

  • What can I pin? The concrete model ids, with the id that actually works as model.

  • May I use it? Whether this brand is permitted to complete on that model with that subscription, right now.

  • How do I reach it? Whether you call us and we call the provider, or you borrow the credential and call the provider yourself.

  • How much room is left? For a borrowed credential, how many accounts are not currently in use.

Before it existed, the only way to find out was to send a real request and read the 400 — and a 400 cannot tell "you're not entitled to this model" apart from "that model doesn't exist".

Before you begin

  • A client credential — Bearer <client_id>:<api_key>:<api_secret>. See Authentication.

  • At least one provider key or subscription in your vault. With an empty vault this call succeeds and returns subscriptions: [], which is a real answer rather than an error.

Your brand comes from the credential. There is no brand_id parameter on this route, so there is nothing to set and nothing to get wrong.

Steps

1. Ask what your brand holds

curl -H "Authorization: Bearer $CLIENT_ID:$API_KEY:$API_SECRET" \
  "https://spideriq.ai/api/gate/v1/subscriptions"

You get one entry per subscription, each with a models list. Full field-by-field detail is in the API reference.

2. Pin the id, not the provider's name for it

Each model carries two names:

::table
Field | Use it for
`id` | This is the one that works. Pass it as `model` on `/chat/completions`.
`provider_model_id` | What the provider calls the same model. Informational.

They are often different — MiniMax's MiniMax-M2.5 is minimax-m2.5-qwen to us. Pinning id is the form that is guaranteed on every subscription.

3. Read two fields before you pin, not one

This is the step that matters most, and the one that is easy to get wrong.

::table
Field | What it promises
`entitled` | **We** permit it. Nothing more.
`probe_status` | We have **seen** this model answer. `null` means never probed — not healthy.

entitled: true with probe_status: null is a permitted but unverified model, and it is the common case, not an edge case. On one real brand on 31 August 2026, of the 25 entitled models the endpoint returned, 2 had a probe status of ok, 8 were error, 2 were delisted, and 13 had never been probed at all.

On the same call, four models reporting entitled: true were refused by their provider — two 404, two 429. The endpoint was not wrong: permission really was ours, and other models on the very same credentials answered normally. Permission and availability are simply two different facts.

So:

  • entitled: false — don't pin it. not_entitled_reason says why.

  • entitled: true, probe_status: "ok" — the strongest signal there is. Prefer these.

  • entitled: true, probe_status: null — pin it only with a fallback, and expect a provider 404 or 429 sometimes.

  • entitled: true, probe_status: "error" or "delisted" — we have watched it fail. Pick something else.

4. Check how the subscription is reached

usage tells you which of two very different things you are holding.

::table
`usage` | What you do | What you get back
`completion` | Call `/chat/completions` with the model id. We reach the provider. | A populated `models` list.
`lease` | Borrow the credential; your own runtime calls the provider. We are never in the completion path. | `lease.free_slots`, `lease.total_slots`, and a `harness` naming the runtime. `models` is deliberately empty.

An empty models list on a leased subscription is correct, not truncated — a borrowed credential is not a menu, because your CLI picks the model.

free_slots is a floor, not a reservation. Leases expire quietly on a timer, so the real number can only go up between your read and your next request. Use it to size a parallel run; don't treat it as capacity someone has set aside for you. Two callers who both read free_slots: 3 can both start three jobs, and one of them will meet a 409.

5. See the same subscriptions in the dashboard

Everything above is also visible to a human. Sign in and open Gate → Vault at /dashboard/gate/vault. Each subscription appears as a key card showing the provider, whether it is active, its health, and its billing mode — the same rows this endpoint reads. If a subscription came back usable: false, the Vault card is where you reconnect or reactivate it.

6. Or let an agent read it for you

If you work through an AI agent, install the gateway skill and ask in plain language:

npx @spideriq/cli skills add @spideriq/gateway-skills

Then, verbatim:

Check which of our SpiderGate subscriptions can actually serve a model right now, and list only the ones whose probe status is ok.

Verify it worked

A healthy response is a 200 whose brand_id matches your own brand and whose subscriptions array has one entry per key in your vault. Cross-check the count against Gate → Vault — they are drawn from the same rows.

To prove the entitlement field is really discriminating rather than saying yes to everything, pick a model with entitled: true and probe_status: "ok" and send it a real completion:

curl -X POST "https://spideriq.ai/api/gate/v1/chat/completions" \
  -H "Authorization: Bearer $CLIENT_ID:$API_KEY:$API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"model":"minimax-m2.5-qwen","messages":[{"role":"user","content":"say ok"}]}'

It should return 200. A model id you invent should return 400 — that contrast is the check.

Troubleshooting

::table
What you see | What it means | What to do
`401 missing_api_key` | No `Authorization` header, or it is malformed. | Send `Bearer <client_id>:<api_key>:<api_secret>` — three parts, colon-separated.
`403 brand_unbound` | The credential is valid but is not tied to a brand, so there is no tenant to answer for. | Use a brand-scoped client credential.
`503 db_unavailable` | The routing engine is still starting. | Retry after a short backoff. Nothing about the request needs to change.
`subscriptions: []` on a `200` | Your brand has no LLM credentials vaulted. | Add one on **Gate → Vault**. This is not an error.
An empty `models` list | Either the subscription is `usage: lease` (correct — your CLI chooses), or no catalog model for that provider is marked configured. | Check `usage` first. If it is `completion`, retry with `?include_unconfigured=true` to see the unconfigured rows.
`usable: false` with `unusable_reason` | The subscription cannot serve anything right now. | Read the reason: `key_inactive` means it was deactivated, often automatically after repeated failures — reconnect it on the Vault page. `consumer_not_permitted` means a leased key has not been opted in to your runner yet.
A model is `entitled` but the provider still refuses | Permission and availability are different facts. | Check `probe_status`. `null` means we have never seen that model answer. Pin one with `probe_status: "ok"`, or keep a fallback.

A freshly connected subscription that you intend to lease is worth a second look: the lease lane is opt-in per key, so a brand-new credential is not leasable by anybody until a consumer is added to its allowlist. Pass your own ?consumer=<your runner id> and the answer will be about your case rather than a generic one.

Related