An agent that picks its own model has to answer a question the gateway never used to expose: of everything on offer, what may this tenant actually run right now?
Until last week the only way to find out was to send a request and read the error. That works, in the way that walking into a door tells you it was closed. It also cannot tell you which kind of closed: a model you are not entitled to and a model that does not exist both come back as a flat 400.
So we built GET /api/gate/v1/subscriptions. It answers four things per subscription, and one of its answers is more interesting than the other three.
The catalogue was never the answer
SpiderGate's model catalogue runs to well over a thousand rows. That list is a statement about the gateway, not about you. It says what we can route to for somebody, not what your brand holds a plan for.

The new endpoint returns the second shape. One entry per credential your brand has vaulted, each with the concrete model ids you may pin. On the brand I tested it against, the catalogue view and the entitlement view differed by two orders of magnitude.
The brand comes from the credential, incidentally. There is no brand_id parameter on the route, which means there is no field in which to put somebody else's.
The interesting answer: permission is not availability
Here is the part worth reading carefully, because a planner that gets it wrong will look correct and fail in production.
The response carries two fields that sound like the same claim and are not.

entitled means we permit it. It is computed with the same predicate the resolver itself uses, so the endpoint can never promise something routing would refuse. That is a real guarantee, and it is narrower than it sounds.
probe_status means we have seen the model answer. And null there does not mean healthy. It means never probed.
I measured this on a live brand on 31 August. Of the 25 models the endpoint reported as entitled:
2 had a probe status of
ok8 were
error2 were
delisted13 had never been probed at all
Two out of twenty-five had actually been seen to work. On the same call, four models reporting entitled: true were refused outright by their provider: two 404, two 429.
The endpoint was not lying. Permission genuinely was ours, and other models on those very same credentials returned 200 seconds later. Permission and availability are simply two different facts about the world, and a field that reports one cannot report the other.
If you are writing a planner, the rule is short:
entitled: false— don't pin it, andnot_entitled_reasontells you why.entitled: truewithprobe_status: "ok"— the strongest signal available. Prefer these.entitled: truewithprobe_status: null— permitted but unproven. Pin it with a fallback and treat a provider404as ordinary.entitled: truewithprobe_status: "error"or"delisted"— we have watched it fail. Choose something else.
We could have collapsed the two into a single cheerful boolean. It would have been friendlier and it would have been a lie roughly nine times out of ten.
Two ways to reach a subscription
The third answer is about shape. Subscriptions are not all the same kind of thing, and the usage field says which kind you are holding.

A completion subscription is the familiar one: you post to /chat/completions with a model id and we reach the provider on your behalf. Those rows carry a populated models list.
A lease subscription is the other thing entirely. You borrow the credential and your own runtime calls the provider; we are never in the completion path at all. Those rows carry a harness naming the runtime the credential gets injected into, and their models list is deliberately empty. That empty array is a correct answer, not a truncated one. A borrowed credential is not a menu, because your CLI is the thing choosing.
Free slots are a floor
The last answer is a number, and numbers invite the wrong kind of confidence.

A lease row reports free_slots and total_slots. total_slots counts the accounts the lease would actually consider, not every row you have vaulted. free_slots is what is left after the ones currently held.
Read it as a floor. Leases expire quietly on a timer and are released without telling anyone, so the true number can only rise between your read and your next request. It is useful for sizing a parallel run. It is not capacity anyone has set aside for you: two callers who both read free_slots: 3 can both start three jobs, and one of them is going to meet a 409.
If Redis is unreachable the read degrades to free_slots: 0 rather than failing outright, so a zero there means no free slot, or we could not tell.
What it is for
If you send spideriq/coding and let us route, none of this concerns you. That is the entire point of an alias.
This endpoint is for the case where something on your side owns the choice, and would rather make it from stated facts than discover it by reading error codes. That turns out to be a growing number of things.
The full field reference, including the complete refusal vocabulary, is in the API reference. There is a shorter walkthrough in Your Subscriptions.
