# Start the managed preview

Start the managed preview

`POST /api/threads/{id}/preview/start`

Required permission: `thread:update`.

## Parameters

| Name | In | Type | Required | Description |

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

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

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

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

| `Idempotency-Key` | header | `string` | No | Required for writes authenticated by a service credential and for service-account lifecycle writes. Other session writes may opt in. Reuse the key and payload for retries. Settled keys remain reserved for at least seven days; a transient 4xx releases its key. Changed payloads return 409. Match any legacy clientOperationId/clientMessageId in the body. |

## Example request

```bash
curl --request POST \
  --url https://api.hoplite.sh/api/threads/id/preview/start \
  --header "X-Api-Key: $HOPLITE_API_KEY" \
  --header "Idempotency-Key: $HOPLITE_OPERATION_ID"
```

## 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.name` | `string` | No | min length 1 | — |
| `preview.status` | `string` | Yes | ready · unsupported · reconciling · blocked · starting · stopped · crashed · inactive | — |
| `preview.port` | `integer` | No | min 1, max 65535 | — |
| `preview.url` | `string<uri>` | No | — | — |
| `preview.reason` | `string` | No | — | — |
| `preview.expiresAt` | `string<date-time>` | No | — | — |
| `preview.oomKilled` | `boolean` | No | — | — |
| `preview.stopProvenance` | `object` | No | — | — |
| `preview.stopProvenance.initiator` | `string` | Yes | hoplite · external · process | — |
| `preview.stopProvenance.source` | `string` | Yes | managed_stop · signal · process_exit · workspace_archive · lifecycle_reconcile | — |
| `preview.stopProvenance.phase` | `string` | Yes | starting · post_ready | — |
| `preview.stopProvenance.signal` | `string` | No | SIGHUP · SIGINT · SIGQUIT · SIGTERM | — |
| `preview.stopProvenance.exitCode` | `integer` | No | min 0, max 255 | — |
| `preview.stopProvenance.occurredAt` | `string<date-time>` | No | — | — |
| `preview.stopProvenance.trigger` | `string` | No | min length 1, max length 64 | — |
| `preview.stopProvenance.cause` | `string` | No | workspace_archive · generation_changed · supervision_lost · exit_unobserved | — |
| `preview.stopProvenance.resumeOnRestore` | `boolean` | No | — | — |
| `preview.requiredResources` | `object` | No | — | — |
| `preview.requiredResources.cpu` | `number` | No | — | — |
| `preview.requiredResources.memoryGiB` | `number` | No | — | — |
| `preview.configuredResources` | `object` | No | — | — |
| `preview.configuredResources.cpu` | `number` | No | — | — |
| `preview.configuredResources.memoryGiB` | `number` | No | — | — |
| `preview.verification` | `object` | No | — | — |
| `preview.verification.http` | `object` | Yes | — | — |
| `preview.verification.http.statusCode` | `integer \| null` | Yes | — | — |
| `preview.verification.http.statusCode.Option 1` | `integer` | No | min -9007199254740991, max 9007199254740991 | — |
| `preview.verification.http.statusCode.Option 2` | `null` | No | — | — |
| `preview.verification.http.responseTimeMs` | `number \| null` | Yes | — | — |
| `preview.verification.http.responseTimeMs.Option 1` | `number` | No | min 0 | — |
| `preview.verification.http.responseTimeMs.Option 2` | `null` | No | — | — |
| `preview.verification.http.finalUrl` | `string<uri> \| null` | Yes | — | — |
| `preview.verification.http.contentType` | `string \| null` | Yes | — | — |
| `preview.verification.http.isHtmlDocument` | `boolean` | Yes | — | — |
| `preview.verification.browser` | `object \| null` | Yes | — | — |
| `preview.verification.browser.Option 1` | `object` | No | — | — |
| `preview.verification.browser.Option 1.available` | `boolean` | Yes | — | — |
| `preview.verification.browser.Option 1.unavailableReason` | `string` | No | deadline-exhausted · service-unavailable | — |
| `preview.verification.browser.Option 1.consoleErrorCount` | `integer` | Yes | min 0, max 9007199254740991 | — |
| `preview.verification.browser.Option 1.consoleErrors` | `object[]` | Yes | max 3 items | — |
| `preview.verification.browser.Option 1.consoleErrors.message` | `string` | Yes | — | — |
| `preview.verification.browser.Option 1.consoleErrors.stack` | `string` | No | — | — |
| `preview.verification.browser.Option 1.uncaughtExceptionCount` | `integer` | Yes | min 0, max 9007199254740991 | — |
| `preview.verification.browser.Option 1.uncaughtExceptions` | `object[]` | Yes | max 3 items | — |
| `preview.verification.browser.Option 1.uncaughtExceptions.message` | `string` | Yes | — | — |
| `preview.verification.browser.Option 1.uncaughtExceptions.stack` | `string` | No | — | — |
| `preview.verification.browser.Option 2` | `null` | No | — | — |
| `preview.verification.error` | `object \| null` | Yes | — | — |
| `preview.verification.error.Option 1` | `object` | No | — | — |
| `preview.verification.error.Option 1.kind` | `string` | Yes | — | — |
| `preview.verification.error.Option 1.reason` | `string` | Yes | — | — |
| `preview.verification.error.Option 2` | `null` | No | — | — |
| `preview.verification.verdict` | `object` | Yes | — | — |
| `preview.verification.verdict.status` | `string` | Yes | ready · degraded · broken | — |
| `preview.verification.verdict.reason` | `string` | Yes | — | — |
| `preview.ports` | `object[]` | No | — | — |
| `preview.ports.name` | `string` | Yes | min length 1 | — |
| `preview.ports.status` | `string` | Yes | ready · unsupported · reconciling · blocked · starting · stopped · crashed · inactive | — |
| `preview.ports.port` | `integer` | No | min 1, max 65535 | — |
| `preview.ports.url` | `string<uri>` | No | — | — |
| `preview.ports.reason` | `string` | No | — | — |
| `preview.ports.expiresAt` | `string<date-time>` | No | — | — |
| `preview.ports.oomKilled` | `boolean` | No | — | — |
| `preview.ports.stopProvenance` | `object` | No | — | — |
| `preview.ports.stopProvenance.initiator` | `string` | Yes | hoplite · external · process | — |
| `preview.ports.stopProvenance.source` | `string` | Yes | managed_stop · signal · process_exit · workspace_archive · lifecycle_reconcile | — |
| `preview.ports.stopProvenance.phase` | `string` | Yes | starting · post_ready | — |
| `preview.ports.stopProvenance.signal` | `string` | No | SIGHUP · SIGINT · SIGQUIT · SIGTERM | — |
| `preview.ports.stopProvenance.exitCode` | `integer` | No | min 0, max 255 | — |
| `preview.ports.stopProvenance.occurredAt` | `string<date-time>` | No | — | — |
| `preview.ports.stopProvenance.trigger` | `string` | No | min length 1, max length 64 | — |
| `preview.ports.stopProvenance.cause` | `string` | No | workspace_archive · generation_changed · supervision_lost · exit_unobserved | — |
| `preview.ports.stopProvenance.resumeOnRestore` | `boolean` | No | — | — |
| `preview.ports.requiredResources` | `object` | No | — | — |
| `preview.ports.requiredResources.cpu` | `number` | No | — | — |
| `preview.ports.requiredResources.memoryGiB` | `number` | No | — | — |
| `preview.ports.configuredResources` | `object` | No | — | — |
| `preview.ports.configuredResources.cpu` | `number` | No | — | — |
| `preview.ports.configuredResources.memoryGiB` | `number` | No | — | — |
| `preview.ports.verification` | `object` | No | — | — |
| `preview.ports.verification.http` | `object` | Yes | — | — |
| `preview.ports.verification.http.statusCode` | `integer \| null` | Yes | — | — |
| `preview.ports.verification.http.statusCode.Option 1` | `integer` | No | min -9007199254740991, max 9007199254740991 | — |
| `preview.ports.verification.http.statusCode.Option 2` | `null` | No | — | — |
| `preview.ports.verification.http.responseTimeMs` | `number \| null` | Yes | — | — |
| `preview.ports.verification.http.responseTimeMs.Option 1` | `number` | No | min 0 | — |
| `preview.ports.verification.http.responseTimeMs.Option 2` | `null` | No | — | — |
| `preview.ports.verification.http.finalUrl` | `string<uri> \| null` | Yes | — | — |
| `preview.ports.verification.http.contentType` | `string \| null` | Yes | — | — |
| `preview.ports.verification.http.isHtmlDocument` | `boolean` | Yes | — | — |
| `preview.ports.verification.browser` | `object \| null` | Yes | — | — |
| `preview.ports.verification.browser.Option 1` | `object` | No | — | — |
| `preview.ports.verification.browser.Option 1.available` | `boolean` | Yes | — | — |
| `preview.ports.verification.browser.Option 1.unavailableReason` | `string` | No | deadline-exhausted · service-unavailable | — |
| `preview.ports.verification.browser.Option 1.consoleErrorCount` | `integer` | Yes | min 0, max 9007199254740991 | — |
| `preview.ports.verification.browser.Option 1.consoleErrors` | `object[]` | Yes | max 3 items | — |
| `preview.ports.verification.browser.Option 1.consoleErrors.message` | `string` | Yes | — | — |
| `preview.ports.verification.browser.Option 1.consoleErrors.stack` | `string` | No | — | — |
| `preview.ports.verification.browser.Option 1.uncaughtExceptionCount` | `integer` | Yes | min 0, max 9007199254740991 | — |
| `preview.ports.verification.browser.Option 1.uncaughtExceptions` | `object[]` | Yes | max 3 items | — |
| `preview.ports.verification.browser.Option 1.uncaughtExceptions.message` | `string` | Yes | — | — |
| `preview.ports.verification.browser.Option 1.uncaughtExceptions.stack` | `string` | No | — | — |
| `preview.ports.verification.browser.Option 2` | `null` | No | — | — |
| `preview.ports.verification.error` | `object \| null` | Yes | — | — |
| `preview.ports.verification.error.Option 1` | `object` | No | — | — |
| `preview.ports.verification.error.Option 1.kind` | `string` | Yes | — | — |
| `preview.ports.verification.error.Option 1.reason` | `string` | Yes | — | — |
| `preview.ports.verification.error.Option 2` | `null` | No | — | — |
| `preview.ports.verification.verdict` | `object` | Yes | — | — |
| `preview.ports.verification.verdict.status` | `string` | Yes | ready · degraded · broken | — |
| `preview.ports.verification.verdict.reason` | `string` | Yes | — | — |

```json

```

## 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.