# DeployState API reference

DeployState turns deployment events into live desktop state. The recommended integration uses a private, per-step webhook URL. Keep this URL in your deployment secret store.

## Private step webhooks

`POST https://deploystate.com/api/v1/hooks/{step_token}/start`

Starts a run when no run is active, or marks the selected step as started in the active run.

`POST https://deploystate.com/api/v1/hooks/{step_token}/complete`

Marks the selected step complete. The run completes when every step has completed.

`POST https://deploystate.com/api/v1/hooks/{step_token}/fail`

Marks the selected step and run failed. An optional JSON body may include a `message` string up to 2,000 characters.

```bash
curl --fail --silent --show-error -X POST \
  'https://deploystate.com/api/v1/hooks/{step_token}/start'
```

## Personal access token endpoints

Generate a personal access token in DeployState settings, then send it as `Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN`.

| Method | Endpoint | Purpose |
| --- | --- | --- |
| GET | `/sequences/active` | Current active runs you can access |
| GET | `/sequences/recent` | Recent completed or failed runs |
| GET | `/ably/token` | A short-lived subscription token for desktop realtime |
| POST | `/{sequence}/{step}/start` | Start a step with a personal access token |
| POST | `/{sequence}/{step}/complete` | Complete a step with a personal access token |
| POST | `/{sequence}/{step}/fail` | Fail a step with a personal access token |

## Friendly hook URLs

Workspaces can also use a readable endpoint instead of the private token in the URL. The step token remains required as a header, so the URL is safe to read but not to invoke without the secret.

`POST https://deploystate.com/api/v1/{sequence_slug}/{step_slug}/start`

```bash
curl --fail --silent --show-error -X POST \
  -H 'X-DeployState-Key: {step_token}' \
  'https://deploystate.com/api/v1/{sequence_slug}/{step_slug}/start'
```

## Responses and errors

Successful hook calls return an empty response body by default. Send `Prefer: return=representation` to receive the updated JSON `sequence_log` and `step_log` instead. A paused sequence returns `422`; an invalid state transition returns `409`; and an invalid private hook token or friendly-hook secret returns `404`.
