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

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/v1

Authentication

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_TOKEN

Reads 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-aliasesmember · list your aliases with their slots

  • GET /dashboard/gate/client-aliases/{name}member · read one, by leaf

  • POST /dashboard/gate/client-aliasesadmin · create one · 201

  • PATCH /dashboard/gate/client-aliases/{name}admin · update one

  • DELETE /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 · default 50 · 1 to 200

  • offset — integer · default 0

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

401

no credential, or one that does not authenticate

send a bearer token

403

your account is not attached to a brand

attach a brand, then retry

500

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

401

no credential, or one that does not authenticate

send a bearer token

404

no alias with that leaf for your brand

check the leaf with a list call

422

the leaf is malformed

send the short leaf, lowercase

500

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 chars

  • description — string · max 500 chars

  • enabled — boolean · default true

  • slots — array, required · 1 to 16 entries

  • slots[].integration_id — integer, required · the key of yours that funds this slot

  • slots[].provider — string, required · max 100 chars

  • slots[].model — string, required · max 200 chars

  • slots[].enabled — boolean · default true

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

401

no credential, or one that does not authenticate

send a bearer token

403

a slot names a key your brand does not own, or that is inactive

use one of your own active key ids

409

you already have an alias with that leaf

pick another leaf, or PATCH the existing one

422

validation failed

read field in the body and fix that input

500

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 chars

  • enabled — boolean

  • slots — 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

401

no credential, or one that does not authenticate

send a bearer token

403

a replacement slot names a key you do not own

use one of your own active key ids

404

no alias with that leaf for your brand

check the leaf with a list call

422

validation failed

read field in the body and fix that input

500

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

401

no credential, or one that does not authenticate

send a bearer token

404

no alias with that leaf for your brand

check the leaf with a list call

422

the leaf is malformed

address the alias by leaf, not by id

500

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 leafname is the short leaf only — do not include a namespace. Send 'cheap', not 'client:7/cheap' …

  • A bad charactername may contain lowercase letters, digits, '-' and '_', and must start and end with a letter or digit

  • A slot with no keyslots[0].integration_id is required — every slot must name the key that pays for it

  • A repeated slotduplicate 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 below

A 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 cheap

Response 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

  1. Find your key ids on the Keys page, or with spideriq gate client-alias list once an alias exists.

  2. Understand what a slot's cost_type means for what it can serve — Task Aliases.

  3. Handle the refusals — Errors.