Developer API
API Reference
Integrate LaunchGuard into your CI/CD workflow. Trigger scans, ingest attack chains, and register ongoing Guard monitoring for any host. Bearer tokens start with lg_.
/api/v1/* routes require a Authorization: Bearer lg_YOUR_TOKEN header. The scan endpoint at /api/scan and Guard registration at /api/skill/register-guard are public and require no auth.https://api.launchguard.dev serves all /api/v1/* routes and /api/skill/register-guard. POST /api/scan is served from https://www.launchguard.dev (the web edge).Error envelope: All error responses return
{ "error": string }. Special cases: POST /chains/{id}/run 409 returns { error, sideEffect: "mutation", needsConfirmation: true }; POST /chains/{id}/restore 409 returns { error, titleCollision: true }.Rate limits:
/api/skill/register-guard is rate-limited (429). List endpoints do not paginate; all results are returned.Scan
/api/scanNo authStart a scan (free, full findings).
Request Body
| Name | Type | Description |
|---|---|---|
| urlrequired | string | The URL to scan. |
| spa | boolean | null | Enable SPA crawling mode (Playwright-backed). |
| maxPages | number | Max pages to crawl (default: 10). |
| jsAssets | number | Max JS bundle files to analyze (default: 5). |
| ffuf | boolean | Run ffuf directory brute-force. |
| includeSubdomains | boolean | Also scan discovered subdomains. |
| client | string | Attribution slug. |
Responses
| Status | Description | ||||||
|---|---|---|---|---|---|---|---|
| 200 | Scan created
| ||||||
| 400 | Error | ||||||
| 500 | Error |
Guard
/api/skill/register-guardNo authRegister Ongoing Guard for a URL (headless, no auth).
Request Body
| Name | Type | Description |
|---|---|---|
| emailrequired | string | |
| target_urlrequired | string |
Responses
| Status | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| 200 | Guard registered
| ||||||||
| 400 | Error | ||||||||
| 429 | Rate limit exceeded. Retry after the Retry-After header interval. | ||||||||
| 500 | Error |
Connect
/api/v1/connectBearer lg_Link this client to the caller's monitor for a host.
Request Body
| Name | Type | Description |
|---|---|---|
| target | string | A public URL or host. |
| url | string | Alias for `target`. |
Responses
| Status | Description | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Connected
| ||||||||||||||||
| 400 | Error | ||||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||||
| 404 | Resource not found. | ||||||||||||||||
| 500 | Error |
Coverage & Context
/api/v1/contextBearer lg_One-call aggregate: redacted inventory + unified tests + coverage + findings.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| targetHost | string | required | The app hostname this chain targets (e.g. acme.app). |
Responses
| Status | Description | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Context
| ||||||||||||||||||||||||
| 400 | Error | ||||||||||||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||||||||||||
| 403 | Forbidden. Token is valid but lacks permission for this operation. | ||||||||||||||||||||||||
| 404 | Resource not found. | ||||||||||||||||||||||||
| 500 | Error |
/api/v1/stacksBearer lg_The test catalog as data; with ?targetHost, per-domain state + verdicts.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| targetHost | string | optional | The app hostname this chain targets (e.g. acme.app). |
Responses
| Status | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| 200 | Stacks
| ||||||||
| 400 | Error | ||||||||
| 401 | Invalid or missing bearer token. | ||||||||
| 403 | Forbidden. Token is valid but lacks permission for this operation. | ||||||||
| 404 | Resource not found. | ||||||||
| 500 | Error |
/api/v1/coverageBearer lg_Toggle a default stack's coverage for the caller's verified host.
Request Body
| Name | Type | Description |
|---|---|---|
| targetHostrequired | string | The app hostname this chain targets (e.g. acme.app). |
| stackIdrequired | string | |
| enabledrequired | boolean | |
| rescanNow | boolean |
Responses
| Status | Description | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Coverage updated
| ||||||||||||||||||||
| 400 | Error | ||||||||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||||||||
| 402 | Error | ||||||||||||||||||||
| 403 | Forbidden. Token is valid but lacks permission for this operation. | ||||||||||||||||||||
| 404 | Resource not found. | ||||||||||||||||||||
| 409 | Error | ||||||||||||||||||||
| 429 | Rate limit exceeded. Retry after the Retry-After header interval. |
Chains
/api/v1/chainsBearer lg_Ingest an attack chain (ChainSpecV2 or script).
Request Body
Responses
| Status | Description | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 201 | Chain stored
| ||||||||||||||
| 400 | Error | ||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||
| 403 | Forbidden. Token is valid but lacks permission for this operation. | ||||||||||||||
| 500 | Error |
/api/v1/chainsBearer lg_List the caller's chains.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| targetHost | string | optional | The app hostname this chain targets (e.g. acme.app). |
| includeArchived | string | optional | Pass 'true' to include soft-deleted (archived) chains in the results. |
Responses
| Status | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| 200 | Chains
| ||||||||
| 400 | Error | ||||||||
| 401 | Invalid or missing bearer token. | ||||||||
| 500 | Error |
/api/v1/chains/credentialsBearer lg_Upload an encrypted Playwright storageState; get an opaque credentialId.
Request Body
Responses
| Status | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| 201 | Credential sealed
| ||||||||
| 400 | Error | ||||||||
| 401 | Invalid or missing bearer token. | ||||||||
| 500 | Error |
/api/v1/chains/{id}Bearer lg_Read one chain's full blueprint.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Responses
| Status | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Chain
| ||||||||||||||||||||||||||||||||||||||||||||||||||
| 400 | Error | ||||||||||||||||||||||||||||||||||||||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| 404 | Resource not found. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| 500 | Error |
/api/v1/chains/{id}Bearer lg_Modify one chain (title/severity/spec/watched).
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Request Body
Responses
| Status | Description | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Updated
| ||||||||||||||||||||||||||||||||||||||
| 400 | Error | ||||||||||||||||||||||||||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||||||||||||||||||||||||||
| 404 | Resource not found. | ||||||||||||||||||||||||||||||||||||||
| 409 | Title collision | ||||||||||||||||||||||||||||||||||||||
| 500 | Error |
/api/v1/chains/{id}Bearer lg_Soft-delete (archive) one chain.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Responses
| Status | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| 200 | Archived
| ||||||||
| 400 | Error | ||||||||
| 401 | Invalid or missing bearer token. | ||||||||
| 404 | Resource not found. | ||||||||
| 500 | Error |
/api/v1/chains/{id}/restoreBearer lg_Un-archive one chain.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Responses
| Status | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| 200 | Restored
| ||||||||
| 400 | Error | ||||||||
| 401 | Invalid or missing bearer token. | ||||||||
| 404 | Resource not found. | ||||||||
| 409 | Title collision on restore. Returns { error, titleCollision: true } — rename the chain before restoring. | ||||||||
| 500 | Error |
/api/v1/chains/{id}/runBearer lg_Re-execute a stored chain through the guarded replay engine.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| confirmMutation | string | optional | Set true to allow a mutating chain to fire real writes. |
Request Body
| Name | Type | Description |
|---|---|---|
| confirmMutation | boolean | string | Opt-in to fire REAL writes for a mutating chain. |
Responses
| Status | Description | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Run result
| ||||||||||||||||||||||
| 400 | Error | ||||||||||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||||||||||
| 403 | Forbidden. Token is valid but lacks permission for this operation. | ||||||||||||||||||||||
| 409 | Chain disabled or mutation gate triggered. Returns { error, sideEffect: "mutation", needsConfirmation: true } — pass confirmMutation: true to allow real writes. | ||||||||||||||||||||||
| 500 | Error |
/api/v1/chains/{id}/dispositionBearer lg_Set/clear the durable disposition layer.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Request Body
| Name | Type | Description |
|---|---|---|
| dispositionrequired | "accepted" | "proposed" | |
| reason | string | Required + non-empty when setting. |
Responses
| Status | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Disposition view
| ||||||||||||||||||
| 400 | Error | ||||||||||||||||||
| 401 | Invalid or missing bearer token. | ||||||||||||||||||
| 403 | Disposition change not permitted in the chain's current state (e.g. already in an incompatible state). | ||||||||||||||||||
| 404 | Resource not found. | ||||||||||||||||||
| 409 | Disposition conflict — the chain state changed since you read it. | ||||||||||||||||||
| 500 | Error | ||||||||||||||||||
| 503 | Disposition service temporarily unavailable. Safe to retry with backoff. |
/api/v1/chains/{id}/run/script/startBearer lg_Start an async script-chain run; get a runId + SSE progress URL.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| confirmMutation | string | optional | Set true to allow a mutating chain to fire real writes. |
Request Body
| Name | Type | Description |
|---|---|---|
| confirmMutation | boolean | string | Opt-in to fire REAL writes for a mutating chain. |
Responses
| Status | Description | ||||||
|---|---|---|---|---|---|---|---|
| 202 | Run started in the background. Returns { runId, progressUrl } — subscribe to the progress SSE stream at progressUrl.
| ||||||
| 400 | Error | ||||||
| 401 | Invalid or missing bearer token. | ||||||
| 403 | Forbidden. Token is valid but lacks permission for this operation. | ||||||
| 404 | Resource not found. | ||||||
| 409 | Disabled, or mutating without confirmation | ||||||
| 500 | Error |
/api/v1/chains/{id}/runs/{runId}/progressBearer lg_Live SSE progress for an async script-chain run.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required | |
| runId | string | required |
Responses
| Status | Description |
|---|---|
| 200 | SSE stream of step + done events |
| 400 | Error |
| 401 | Invalid or missing bearer token. |
| 404 | Resource not found. |
/api/v1/chains/{id}/traces/{token}Bearer lg_Download an owner-only, expiring trace.zip for a run.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required | |
| token | string | required |
Responses
| Status | Description |
|---|---|
| 200 | The trace.zip archive |
| 400 | Error |
| 401 | Invalid or missing bearer token. |
| 404 | Resource not found. |
/api/v1/chains/{id}/runs/{runId}/videoBearer lg_Owner-only gated HLS replay proxy for a script-chain run recording.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | required | |
| runId | string | required |
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| segment | string | optional |
Responses
| Status | Description |
|---|---|
| 200 | HLS manifest (no ?segment) or a single media/init segment (with ?segment) |
| 401 | Invalid or missing bearer token. |
| 404 | Resource not found. |
Type Reference
Shared schemas referenced across multiple endpoints.
Severity
Finding/chain severity.
SideEffect
Declared/derived side-effect class.
ChainSource
Defaults to ai_agent.
ChainMethod
TargetRef
Host enum resolved against spec.allowedTargets (never free-form).
Disposition
'accepted' | 'proposed' | null (null clears the disposition).
DispositionState
EffectiveStatus
CredentialsBody
A Playwright storageState (raw or wrapped in { storageState, ... }).
Option 1 (storageState)
| Name | Type | Description |
|---|---|---|
| storageStaterequired | string | object | Playwright storageState (either raw JSON or wrapped in { storageState, label, metadata }). |
| label | string | Human-readable label for a chain step or stored credential. |
| metadata | object | |
| identity | object |
Option 2 (cookies/origins)
| Name | Type | Description |
|---|---|---|
| cookies | object[] | |
| origins | object[] |
PatchChainBody
At least one of title|severity|spec|watched must be provided.
| Name | Type | Description |
|---|---|---|
| title | string | Human-readable title, unique per host. |
| severity | "critical" | "high" | "medium" | "low" | Finding severity level. |
| spec | HttpChainSpec | ScriptChainSpec | |
| watched | boolean | true = Guard mode (re-runs on deploy); false = Proof only (default). |
IngestChainBody
| Name | Type | Description |
|---|---|---|
| titlerequired | string | Human title (unique per host). |
| targetHostrequired | Host | The app hostname this chain targets (e.g. acme.app). |
| severityrequired | "critical" | "high" | "medium" | "low" | Finding severity level. |
| source | "scanner" | "ai_agent" | "e2e_test" | "manual" | "import" | Who generated this chain (defaults to ai_agent). |
| bin | string | Bin/namespace tag for organizing chains. |
| watched | boolean | true=Guard (re-runs on deploy); default false=Proof. |
| artifact | string | Defaults to http. |
| spec | HttpChainSpec | ScriptChainSpec | The ChainSpecV2 (HTTP chains). |
| script | string | @playwright/test source (artifact:script). |
| intent | string | Chain intent: security or functional. |
| secureWhen | string | When pass, the test is secure when assertions pass. |
| sideEffect | "none" | "read_only" | "mutation" | "external_action" | |
| destructive | boolean | Mark chain as potentially destructive. |
| credentialId | string | Reference to a stored Playwright credential set. |
| allowedTargets | object |
HttpChainSpec
| Name | Type | Description |
|---|---|---|
| versionrequired | number | |
| stepsrequired | ChainStep[] | |
| assertionrequired | SecurityAssertion | |
| authrequired | object | |
| sideEffectrequired | "none" | "read_only" | "mutation" | "external_action" | |
| allowedTargetsrequired | AllowedTargets | |
| env | object | |
| inventoryHash | string |
ScriptChainSpec
| Name | Type | Description |
|---|---|---|
| versionrequired | number | |
| artifactrequired | string | Chain type: http (default) or script (Playwright). |
| stepsrequired | ChainStep[] | |
| assertionrequired | SecurityAssertion | |
| authrequired | object | |
| sideEffectrequired | "none" | "read_only" | "mutation" | "external_action" | |
| allowedTargetsrequired | AllowedTargets | |
| scriptrequired | ScriptChainPayload | |
| env | object | |
| inventoryHash | string |
ChainStep
| Name | Type | Description |
|---|---|---|
| orderrequired | number | |
| idrequired | string | |
| labelrequired | string | Human-readable label for a chain step or stored credential. |
| requestrequired | ChainRequestSpec | |
| rolerequired | string | |
| authRef | string | |
| extract | ChainExtractor[] | |
| sideEffectrequired | "none" | "read_only" | "mutation" | "external_action" |
ChainRequestSpec
| Name | Type | Description |
|---|---|---|
| methodrequired | "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | |
| targetrequired | "primary" | "supabase" | "api" | Host enum resolved against spec.allowedTargets: 'primary' | 'supabase' | 'api'. Never a free-form URL. |
| pathrequired | string | |
| query | object | |
| headers | object | |
| body | object | |
| timeoutMs | number |
ChainExtractor
| Name | Type | Description |
|---|---|---|
| asrequired | string | |
| fromrequired | string | |
| expr | string | |
| index | number | |
| requiredrequired | boolean |
SecurityAssertion
| Name | Type | Description |
|---|---|---|
| successStatusInrequired | number[] | |
| fixedStatusInrequired | number[] | |
| crossTenant | object | |
| minTotalRows | number | |
| jsonPathsPresent | string[] | |
| bodyContainsAll | string[] | |
| contentTypeIncludes | string | |
| errorEnvelopeContainsAny | string[] |
ChainAuthRef
| Name | Type | Description |
|---|---|---|
| credentialIdrequired | string | null | Reference to a stored Playwright credential set. |
| injectrequired | string |
AllowedTargets
| Name | Type | Description |
|---|---|---|
| primaryrequired | string | |
| supabase | string | |
| api | string |
Proof
Option 1 (RowsProof)
| Name | Type | Description |
|---|---|---|
| renderrequired | string | |
| countrequired | number | |
| columnsrequired | string[] | |
| sampleRowsrequired | object[] | Each value is value-masked before it leaves the engine. |
| moreCountrequired | number | |
| countIsFloor | boolean |
Option 2 (RecordWithOwnerProof)
| Name | Type | Description |
|---|---|---|
| renderrequired | string | |
| foreignRowCountrequired | number | |
| sampleRowrequired | object | |
| ownerValuerequired | string | |
| comparedAgainstUserIdrequired | string |
Option 3 (JudgmentOnlyProof)
| Name | Type | Description |
|---|---|---|
| renderrequired | string | |
| reasonrequired | string | |
| codeRef | string |
ObservedSnapshot
| Name | Type | Description |
|---|---|---|
| statusrequired | number | |
| contentTyperequired | string | |
| rowCountrequired | number | null | |
| jsonKeysrequired | string[] | |
| bodyPreviewrequired | string | Value-masked before it leaves the engine. |
Reproduced
| Name | Type | Description |
|---|---|---|
| passedrequired | number | |
| totalrequired | number |