| GET | /api/projects/{id}/preview?sessionId= | Preview URLs by route key. Starts or resumes the sandbox if it is not running. Omit sessionId for the project's main sandbox. Returns creditLimitReached: true instead of starting one when the workspace is out of credits. |
| GET | /api/projects/{id}/preview/health?sessionId= | Per-service container status and HTTP health. |
| POST | /api/projects/{id}/preview/reset | Restart the services in place. Body { sessionId }. Fails if the sandbox is paused or unreachable. |
| GET | /api/projects/{id}/preview/auth-token?sessionId= | Short-lived token appended to a preview URL so the proxy can admit the request. |
| GET | /api/projects/{id}/preview/share?sessionId= | The current link as { slug, url, createdAt, lastViewedAt }, or { "share": null } when there is none. lastViewedAt is null until opened, then moves at most once every five minutes. Omit sessionId for the main preview. |
| POST | /api/projects/{id}/preview/share | Mint the link, or hand back the one that already exists. Optional body { sessionId }; an absent or unparseable body means the main preview. Any workspace member may do this, there is no admin-role gate. |
| DELETE | /api/projects/{id}/preview/share?sessionId= | Revoke the link by deleting the row, so there is no revoked state to find it in. Idempotent: revoking a link that is already gone succeeds and answers { "share": null }. |