/api/public/v1/sessions/{id}/detachsessions.detach
Release your app hold without stopping the browser: it stays warm for keep_warm_seconds (0–1800) and stops then unless a person, a run or an app takes it again.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
idpath | string (uuid) | Yes | Session id |
command_idbody | string (uuid) | Yes | Client-generated UUID for this command. Send the same id (and body) again to get the stored receipt instead of a second change; a different body under the same id is CONFLICT. |
generationbody | integer | Yes | lease.generation from acquire (min 1, max 9007199254740991) |
holder_refbody | string | Yes | Your stable name for this holder (worker, job); renew and detach must send the same value (min length 1, max length 120) |
keep_warm_secondsbody | integer | No | Override the keep-warm time given at acquire (min 0, max 1800) |
Examples
curl -X POST "https://browlix.com/api/public/v1/sessions/<id>/detach" \
-H "Authorization: Bearer $BROWLIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"command_id":"<uuid>","generation":0,"holder_ref":"<holder_ref>"}'Response
201 with { data, replayed: false, correlation_id } the first time; 200 with replayed: true when the same command_id and body come again.
| Field | Type | Always present | Description |
|---|---|---|---|
| data | object | Yes | |
| data.id | string (uuid) | Yes | |
| data.lifecycle | "queued" | "preflight" | "starting" | "ready" | "quiescing" | "stopping" | "closed" | "failed" | … | Yes | |
| data.control | "free" | "reserved" | "controlled" | "handoff_pending" | "revoked" | "uncertain" | Yes | |
| data.connectivity | "connected" | "reconnecting" | "offline" | "unknown" | Yes | |
| data.network | "unchecked" | "checking" | "healthy" | "unhealthy" | "unknown" | Yes | |
| data.sync | "clean" | "dirty" | "snapshotting" | "upload_pending" | "committing" | "committed" | "conflict" | "failed" | Yes | |
| data.fence | integer | Yes | Increments every time the profile is opened; stale reports carry an older fence (min -9007199254740991, max 9007199254740991) |
| data.revision | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| data.headless | boolean | Yes | |
| data.profile | object | Yes | |
| data.profile.id | string (uuid) | Yes | |
| data.profile.os | "windows" | "linux" | Yes | |
| data.profile.name | string | Yes | |
| data.profile.number | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| data.profile.group_id | string (uuid) | null | Yes | |
| data.profile.revision | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| data.device | object | Yes | |
| data.device.id | string (uuid) | Yes | |
| data.device.os | "windows" | "linux" | Yes | |
| data.device.name | string | Yes | |
| data.device.state | string | Yes | |
| data.device.freshness | string | Yes | |
| data.lease | object | Yes | Your app's hold after letting go |
| data.lease.session_id | string (uuid) | Yes | |
| data.lease.app_id | string | Yes | |
| data.lease.binding_id | string (uuid) | null | No | |
| data.lease.holder_ref | string | Yes | |
| data.lease.generation | integer | Yes | Send with renew and detach; an older generation is FENCED (min -9007199254740991, max 9007199254740991) |
| data.lease.state | "active" | "detached" | "lapsed" | "ended" | Yes | |
| data.lease.ttl_seconds | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| data.lease.keep_warm_seconds | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| data.lease.acquired_at | string (date-time) | Yes | |
| data.lease.expires_at | string (date-time) | Yes | |
| data.lease.keep_warm_until | string (date-time) | No | |
| data.lease.ended_reason | string | No | |
| data.egress | object | null | Yes | |
| data.egress.ip | string | Yes | |
| data.egress.checked_at | string (date-time) | Yes | |
| data.process | object | null | Yes | |
| data.process.pid | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| data.runtime | object | null | Yes | |
| data.runtime.channel | string | Yes | |
| data.runtime.version | string | Yes | |
| data.identity | object | null | Yes | What the browser actually reported (user agent, languages, timezone, …) |
| data.mismatches | array<object> | Yes | |
| data.remote | object | null | Yes | |
| data.proxy_id | string (uuid) | null | Yes | |
| data.run_id | string (uuid) | null | Yes | |
| data.run_target_id | string (uuid) | null | Yes | |
| data.started_by | string | null | Yes | |
| data.stopped_by | string | null | Yes | |
| data.stop_reason | string | null | Yes | |
| data.reason_code | string | null | Yes | |
| data.network_reason | string | null | Yes | |
| data.ready_ms | integer | null | Yes | |
| data.ready_at | string (date-time) | null | Yes | |
| data.closed_at | string (date-time) | null | Yes | |
| data.created_at | string (date-time) | Yes | |
| data.updated_at | string (date-time) | Yes | |
| data.attach_open | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| data.pending_changes | boolean | Yes | |
| data.profile_revision | integer | Yes | (min -9007199254740991, max 9007199254740991) |
| correlation_id | string (uuid) | Yes | |
| replayed | boolean | No | true when this command_id was already applied and the stored receipt came back |
Errors
| Code | HTTP | Retryable |
|---|---|---|
| UNAUTHENTICATED | 401 | No |
| FORBIDDEN | 403 | No |
| RATE_LIMITED | 429 | Yes |
| VALIDATION_FAILED | 422 | No |
| NOT_FOUND | 404 | No |
| CONFLICT | 409 | No |
| OUTCOME_UNKNOWN | 202 | Yes |
| DEPENDENCY_UNAVAILABLE | 503 | Yes |
| UNKNOWN | 500 | No |
