---
title: 'REST API: Lookups'
path: reference/rest-api/lookups
status: published
---

# REST API: Lookups

Read-only proxies into ScaiQueue, ScaiBunker, and ScaiGrid. Used by the canvas so the browser never holds tenant credentials and CORS stays out of the way.

All endpoints under `/api/v1/scaiqueue/*`, `/api/v1/scaibunker/*`, `/api/v1/scaigrid/*`. All require `scaicore:view`.

## Auth precedence

The proxy resolves the upstream auth in this order (configurable via `SCAIFLOW_DEPLOY_AUTH`):

1. Caller's ScaiKey JWT (forwarded verbatim).
2. Per-tenant `sgk_*` API key from ScaiVault (`tenants/{tenant_id}/scaigrid_api_key`).
3. `SCAIGRID_API_KEY` env var fallback (dev only).

If none are available, returns `412 missing_credentials` with a `fix:` hint pointing the user at `POST /v1/tenants/me/scaigrid_credentials`.

## ScaiQueue

### `GET /v1/scaiqueue/scopes`

List all ScaiQueue scopes visible to the tenant.

**Response:**

```jsonc
{
  "data": [
    { "id": "sc_xxx", "slug": "support",
      "display_name": "Support workflows", "description": "..." }
  ]
}
```

### `GET /v1/scaiqueue/scopes/{scope_id}/queues`

List queues in a scope.

**Response:**

```jsonc
{
  "data": [
    { "id": "q_xxx", "scope_id": "sc_xxx", "slug": "review",
      "display_name": "Review queue", "consumer_mode": "fifo", "max_retries": 5 }
  ]
}
```

## ScaiBunker

### `GET /v1/scaibunker/bunkers`

List currently-active bunkers (running or persistent) visible to the tenant.

**Response:**

```jsonc
{
  "data": [
    { "bunker_id": "bnk_xxx", "image_ref": "python-3.12",
      "lifecycle": "ephemeral", "status": "ready", ... }
  ]
}
```

## ScaiGrid

### `GET /v1/scaigrid/models`

The tenant's frontend-model catalog from ScaiGrid. Used by the canvas Model Picker.

**Response:**

```jsonc
{
  "data": [
    { "slug": "openai/gpt-4o", "display_name": "GPT-4o",
      "modality": "chat", "context_window": 128000, "max_output_tokens": 16384 },
    { "slug": "scailabs/poolnoodle-omni", "display_name": "Poolnoodle Omni",
      "modality": "chat", "context_window": 256000 },
    { "slug": "openai/gpt-4o-mini", "display_name": "GPT-4o mini",
      "modality": "chat", "context_window": 128000 }
  ]
}
```

The proxy normalizes two upstream response envelopes:

- Native ScaiGrid `{"data": [{"slug": ...}, ...]}`.
- OpenAI-compat `{"object": "list", "data": [{"id": "openai/gpt-4o", "object": "model", ...}, ...]}` — the `id` field is mapped to `slug` so the canvas sees one shape.

Also tolerant of `{"data": {"items": [...]}}` nested-pagination wrappers some ScaiGrid deployments use.

## Error shapes

All proxies surface upstream errors as `502 Bad Gateway` with a structured detail:

```jsonc
{
  "detail": {
    "error": "scaiqueue_auth",
    "message": "permission_denied: need scaiqueue:view",
    "fix": "Caller needs the `scaiqueue:view` permission on this tenant."
  }
}
```

Variants:

| `error` value | Meaning |
|---|---|
| `scaiqueue_auth` / `scaibunker_auth` / `scaigrid_auth` | Upstream returned 401/403. |
| `scaiqueue_api` / `scaibunker_api` / `scaigrid_api` | Upstream returned a non-auth error (4xx/5xx); `status` + `code` carry the upstream's values. |
| `missing_credentials` | No JWT, no tenant API key configured. 412 response. |
