# Issue preview gateway access

Inspect the existing preview without starting it, then receive a fresh five-minute server-only gateway credential for its URL. Start the preview first with startThreadPreview. Supply frameOrigin as the exact HTTPS dashboard origin. Relay HTTP and WebSocket requests through your authenticated backend to preview.url with the credential in X-Hoplite-Preview-Token; never expose it to browsers. Project restrictions are enforced when access is issued; revoking a credential stops new grants but not an unexpired one.

`GET /api/threads/{id}/preview/access`

Required permission: `thread:read`.

## Parameters

| Name | In | Type | Required | Description |

| --- | --- | --- | --- | --- |

| `id` | path | `string` | Yes | — |

| `frameOrigin` | query | `string<uri>` | Yes | — |

| `name` | query | `string` | No | — |

| `port` | query | `integer` | No | — |

## Example request

```bash
curl --request GET \
  --url https://api.hoplite.sh/api/threads/id/preview/access?frameOrigin=frameOrigin \
  --header "X-Api-Key: $HOPLITE_API_KEY"
```

## 200 response

Successful response

Content type: `application/json`. Response type: `object`.

| Field | Type | Required | Constraints | Description |
| --- | --- | --- | --- | --- |
| `ok` | `boolean` | Yes | constant true | — |
| `preview` | `object` | Yes | — | — |
| `preview.status` | `string` | Yes | ready · unsupported · reconciling · blocked · starting · stopped · crashed · inactive | — |
| `preview.name` | `string` | No | min length 1 | — |
| `preview.port` | `integer` | No | min 1, max 65535 | — |
| `preview.reason` | `string` | No | — | — |
| `preview.url` | `string<uri>` | No | — | — |
| `preview.gateway` | `object \| null` | Yes | — | — |
| `preview.gateway.Option 1` | `object` | No | — | — |
| `preview.gateway.Option 1.header` | `string` | Yes | constant "x-hoplite-preview-token" | — |
| `preview.gateway.Option 1.token` | `string` | Yes | — | — |
| `preview.gateway.Option 1.expiresAt` | `string<date-time>` | Yes | — | — |
| `preview.gateway.Option 2` | `null` | No | — | — |

```json
{
  "ok": true,
  "preview": {
    "status": "ready",
    "name": "preview",
    "port": 3000,
    "url": "https://preview-token.preview.hoplite.sh/",
    "gateway": {
      "header": "x-hoplite-preview-token",
      "token": "signed-gateway-token",
      "expiresAt": "2026-09-22T10:05:00.000Z"
    }
  }
}
```

## Response headers

| Header | Type | Statuses | Description |

| --- | --- | --- | --- |

| `RateLimit` | `string` | `200`, `400`, `401`, `402`, `403`, `404`, `409`, `410`, `429`, `500`, `501`, `503` | Current ingress policy, remaining requests, and seconds until reset, for example `"ingress";r=599;t=60`. |

| `RateLimit-Policy` | `string` | `200`, `400`, `401`, `402`, `403`, `404`, `409`, `410`, `429`, `500`, `501`, `503` | Ingress quota and window, for example `"ingress";q=600;qu="requests";w=60`. |

| `X-RateLimit-Limit` | `integer` | `200`, `400`, `401`, `402`, `403`, `404`, `409`, `410`, `429`, `500`, `501`, `503` | Maximum requests allowed in the current rolling window. |

| `X-RateLimit-Remaining` | `integer` | `200`, `400`, `401`, `402`, `403`, `404`, `409`, `410`, `429`, `500`, `501`, `503` | Requests remaining in the current rolling window. |

| `X-RateLimit-Reset` | `integer` | `200`, `400`, `401`, `402`, `403`, `404`, `409`, `410`, `429`, `500`, `501`, `503` | Unix timestamp when the current rolling window resets. |

| `x-request-id` | `string` | `200`, `400`, `401`, `402`, `403`, `404`, `409`, `410`, `429`, `500`, `501`, `503` | Request correlation ID. |

| `Retry-After` | `integer` | `429`, `503` | Seconds until another request should be attempted. |

| `X-Retry-After` | `integer` | `429`, `503` | Legacy retry delay in seconds. |

## Status codes

- `200` — Successful response

- `400` — Invalid request. Validation responses include field paths.

- `401` — The API key is missing, invalid, or lacks the operation's permission.

- `402` — The organization does not have access to the requested product capability.

- `403` — The key's current user no longer has the required organization membership or role.

- `404` — The resource is not available in the authenticated scope.

- `409` — The request conflicts with a retry receipt or current resource state.

- `410` — The event cursor has expired; capture a fresh head and resource snapshot.

- `429` — The API-key rate limit has been exceeded.

- `500` — The API encountered an unexpected failure.

- `501` — The deployment has not configured the requested capability.

- `503` — A required API dependency, including the rate limiter, is unavailable.