Client Aliases API
A client alias is a routing name you define yourself. You give it a short leaf — cheap — and SpiderGate publishes it as client:<your-brand-id>/cheap. Behind it sits a set of slots, and every slot names one of your own provider keys. When a completion asks for that name, SpiderGate serves it from those slots — on your keys, and only on your keys.
This is the tenant-scoped CRUD surface for those aliases. Five endpoints: list, read, create, update, delete.
If you are deciding whether to use client aliases, read Your Own Routing Aliases first — it is the same feature explained for a human rather than for a caller.
Base URL
https://spideriq.ai/api/v1Authentication
Send a bearer token — either a personal access token or the legacy client_id:api_key:api_secret triple. Both work on every endpoint here.
Authorization: Bearer $SPIDERGATE_TOKENReads need member on the brand. Every write needs admin — a client_user may look at an alias but may not arm one.
Your tenant is never in the request
There is no brand_id path segment, no brand_id query parameter and no brand_id body field on any endpoint below. Your brand comes from the credential you authenticate with.
That is deliberate, and it is stronger than a permission check. A request naming another tenant is not rejected here — it is unformulatable, because there is no field in which to name them. Ask for an alias that belongs to somebody else and you get 404, exactly as if it did not exist; a 403 would confirm that it does.
Naming
You supply the leaf only. The client:<brand>/ prefix is generated by the database and cannot be sent, so a client alias can never collide with spideriq/*, agent/* or opvs/*.
::table
Rule | Value
Pattern | `^[a-z0-9]([a-z0-9_-]{0,62}[a-z0-9])?$`
Max length | 64 characters
Case | lowercased on the way in
Resolvable form | `client:<your-brand-id>/<leaf>`Slots are a pool, not a fallback ladder
This is the one thing to get right, because the obvious reading is the wrong one.
Every eligible slot receives traffic. SpiderGate picks between them by least busy — the same contract its own spideriq/* chains have. The slot number is a stable display and tie-break order; it is not a priority, and slot 0 is not "the primary".
To make one model primary, remove the others — do not reorder them.
A slot that is not eligible is dropped, and the remaining slots carry on. Only when every slot has been dropped does the alias refuse, with client_alias_no_eligible_key. It never falls through to a spideriq/* alias and never reaches SpiderIQ's shared capacity.
Endpoint summary
GET /dashboard/gate/client-aliases— member · list your aliases with their slotsGET /dashboard/gate/client-aliases/{name}— member · read one, by leafPOST /dashboard/gate/client-aliases— admin · create one ·201PATCH /dashboard/gate/client-aliases/{name}— admin · update oneDELETE /dashboard/gate/client-aliases/{name}— admin · delete one ·204
Managing aliases is not metered. Meters fire on completions, never on this surface.
GET /dashboard/gate/client-aliases
List every alias your brand owns, newest first, each with its ordered slots.
limit— integer · default50· 1 to 200offset— integer · default0
curl -s "https://spideriq.ai/api/v1/dashboard/gate/client-aliases?limit=5" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN"Response — a brand with no aliases yet returns an empty page rather than an error:
{"items": [], "total": 0, "limit": 5, "offset": 0}Each entry in items carries the alias record and its slots:
{
"id": 6,
"brand_id": 9,
"name": "cheap",
"alias": "client:9/cheap",
"description": "Cheapest chain that still does tool calls",
"enabled": true,
"created_by": "you@example.com",
"created_at": "2026-09-03T13:41:02Z",
"updated_at": "2026-09-03T13:41:02Z",
"slots": [
{
"slot": 0,
"provider": "groq",
"model": "llama-3.3-70b-versatile",
"integration_id": 142,
"enabled": true,
"key_provider": "groq",
"key_label": "Groq production",
"cost_type": "paid",
"key_is_active": true
}
]
}The four key_* fields are read back from the key each slot names, so you can see a slot has gone stale — a key switched off, or a key type that will not serve the model — without opening the Keys page. No credential is ever returned on this surface.
Errors:
Status | Trigger | What to do |
|---|---|---|
| no credential, or one that does not authenticate | send a bearer token |
| your account is not attached to a brand | attach a brand, then retry |
| unexpected server fault | retry; if it persists, contact support |
GET /dashboard/gate/client-aliases/{name}
Read one alias by its short leaf, not by its resolvable name and not by its numeric id.
curl -s "https://spideriq.ai/api/v1/dashboard/gate/client-aliases/cheap" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN"Response is a single alias object, the same shape as one items entry above.
An unknown leaf and another tenant's leaf return the same 404 on purpose:
{"error": {"code": "HTTP_ERROR_404", "message": "no alias named 'no-such-alias'"}}Errors:
Status | Trigger | What to do |
|---|---|---|
| no credential, or one that does not authenticate | send a bearer token |
| no alias with that leaf for your brand | check the leaf with a list call |
| the leaf is malformed | send the short leaf, lowercase |
| unexpected server fault | retry; if it persists, contact support |
POST /dashboard/gate/client-aliases
Create an alias. Returns 201.
Creating publishes. The alias is resolvable by your tenant the moment this call returns — there is no separate publish step. Send "enabled": false to author a chain without arming it.
name— string, required · the short leaf, 1–64 charsdescription— string · max 500 charsenabled— boolean · defaulttrueslots— array, required · 1 to 16 entriesslots[].integration_id— integer, required · the key of yours that funds this slotslots[].provider— string, required · max 100 charsslots[].model— string, required · max 200 charsslots[].enabled— boolean · defaulttrue
curl -s -X POST "https://spideriq.ai/api/v1/dashboard/gate/client-aliases" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "cheap",
"description": "Cheapest chain that still does tool calls",
"slots": [
{"integration_id": 142, "provider": "groq", "model": "llama-3.3-70b-versatile"},
{"integration_id": 143, "provider": "openrouter", "model": "openai/gpt-oss-120b"}
]
}'Response is the created alias, with alias filled in as client:<your-brand-id>/cheap.
The one worth handling is 403, which is the ownership wall:
{"error": {"code": "HTTP_ERROR_403", "message": "slot 0 names key 999999, which is not an active key belonging to this brand. A client alias may only use keys you own."}}Errors:
Status | Trigger | What to do |
|---|---|---|
| no credential, or one that does not authenticate | send a bearer token |
| a slot names a key your brand does not own, or that is inactive | use one of your own active key ids |
| you already have an alias with that leaf | pick another leaf, or |
| validation failed | read |
| unexpected server fault | retry; if it persists, contact support |
PATCH /dashboard/gate/client-aliases/{name}
Update an alias. Only the fields you send change.
⚠️ slots REPLACES the whole slot set — it does not merge. Read the alias first and send back the full list, including the slots you are keeping. Sending "description": null clears the description; omitting description leaves it alone.
description— string or null · max 500 charsenabled— booleanslots— array · 1 to 16 entries · replaces the entire slot set
curl -s -X PATCH "https://spideriq.ai/api/v1/dashboard/gate/client-aliases/cheap" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'Response is the updated alias, in the same shape as a read.
Errors:
Status | Trigger | What to do |
|---|---|---|
| no credential, or one that does not authenticate | send a bearer token |
| a replacement slot names a key you do not own | use one of your own active key ids |
| no alias with that leaf for your brand | check the leaf with a list call |
| validation failed | read |
| unexpected server fault | retry; if it persists, contact support |
DELETE /dashboard/gate/client-aliases/{name}
Delete an alias and its slots permanently. Returns 204 with no body.
Address it by leaf. Passing the numeric id returns 404, because the id is not the address.
curl -s -o /dev/null -w "%{http_code}\n" -X DELETE \
"https://spideriq.ai/api/v1/dashboard/gate/client-aliases/cheap" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN"Response: 204, empty body. The create and the delete both stay in your alias audit log; that is a record, not residue.
After deletion, completions naming that alias are refused — they do not quietly fall back to a spideriq/* alias or to the SpiderIQ pool. If you may want the alias back, prefer PATCH with "enabled": false.
Errors:
Status | Trigger | What to do |
|---|---|---|
| no credential, or one that does not authenticate | send a bearer token |
| no alias with that leaf for your brand | check the leaf with a list call |
| the leaf is malformed | address the alias by leaf, not by id |
| unexpected server fault | retry; if it persists, contact support |
Errors
Every failure on this surface is typed. A validation error also names the field that caused it.
::table
Status | When | Body
`401` | no credential, or one that does not authenticate | `Not authenticated. Provide a session cookie or Bearer token.`
`403` | a slot names a key your brand does not own or that is inactive | `slot N names key K, which is not an active key belonging to this brand. A client alias may only use keys you own.`
`403` | your account is not attached to a brand | `No brand is associated with this account.`
`404` | no alias with that leaf — including one owned by another tenant | `no alias named 'X'`
`409` | you already have an alias with that leaf | `an alias named 'X' already exists`
`409` | your client row has no brand, so it cannot own keys | `This account is not attached to a brand …`
`422` | validation — the leaf, or a slot | `field` names what to fix
`500` | anything unexpected | `Internal server error`Four 422 messages you are most likely to meet:
A full alias instead of a leaf —
name is the short leaf only — do not include a namespace. Send 'cheap', not 'client:7/cheap' …A bad character —
name may contain lowercase letters, digits, '-' and '_', and must start and end with a letter or digitA slot with no key —
slots[0].integration_id is required — every slot must name the key that pays for itA repeated slot —
duplicate slot groq/m on the same key — a repeated slot is not extra capacity, it is unreachable
The last one is not pedantry. Two identical (key, provider, model) slots collapse into one deployment, so the second could never be reached.
Using the alias in a completion
Send the resolvable name as model on the ordinary chat-completions endpoint. Nothing else changes.
curl -s "https://spideriq.ai/api/gate/v1/chat/completions" \
-H "Authorization: Bearer $SPIDERGATE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"model": "client:9/cheap", "messages": [{"role": "user", "content": "Say hello"}]}'Response is an ordinary OpenAI-shaped completion. Your own key paid for it.
When an alias cannot serve, the request is refused rather than rerouted. SpiderGate never silently falls back from your alias to its own pool:
::table
Refusal | Meaning
`client_alias_not_found` | no alias with that name for your brand
`client_alias_disabled` | the alias exists but is not armed
`client_alias_no_slots` | the chain is empty
`client_alias_no_eligible_key` | every slot was dropped — see the drop reasons belowA slot is dropped for one of five reasons: key_missing, key_inactive, key_not_owned, key_inject_only, or key_type_forbids_model. Dropping one slot is not fatal — the others still serve. Only an alias where every slot was dropped refuses.
Errors on the completion path are the gateway's own — see Errors.
From the CLI
spideriq gate client-alias list
spideriq gate client-alias get cheap
spideriq gate client-alias create cheap --slots '[{"integration_id":142,"provider":"groq","model":"llama-3.3-70b-versatile"}]'
spideriq gate client-alias update cheap --disable
spideriq gate client-alias delete cheapResponse for each is the JSON above; add --format yaml for YAML.
gate client-alias is your own aliases. gate aliases is a different command — it lists the spideriq/* task aliases we maintain. Errors match the API exactly.
From an agent
@spideriq/mcp-gate exposes the same five operations as tools: gate_client_alias_list, gate_client_alias_get, gate_client_alias_create, gate_client_alias_update and gate_client_alias_delete.
None of them takes a tenant argument, for the same reason the HTTP surface does not — an agent acting for you cannot name anybody else's brand.
Next steps
Find your key ids on the Keys page, or with
spideriq gate client-alias listonce an alias exists.Understand what a slot's
cost_typemeans for what it can serve — Task Aliases.Handle the refusals — Errors.