Trigger a production deployment of your store programmatically – the API equivalent of the admin Publish button. Only stores with platform-managed deployments can use these endpoints.

## Trigger Publish

```
POST /api/v1/publish
```

Starts a production build and deployment of the store's `main` branch. Returns `202` immediately with a `publishId` – poll `GET /api/v1/publish/{publishId}` to track progress.

This endpoint requires the **store API key** (`sk-...`). OAuth tokens are not accepted and will receive a `403`.

```bash
curl -X POST \
  -H "Authorization: Bearer sk_your_api_key" \
  https://your-store.yns.store/api/v1/publish
```

### Response (202)

```json
{
  "publishId": "0199f0a1-7c3e-7a21-9f2d-6b1f0c4a8e55",
  "status": "queued",
  "deploymentId": "dpl_abc123",
  "deploymentUrl": "store-abc123.vercel.app",
  "inspectorUrl": "https://vercel.com/...",
  "savedChanges": true
}
```

| Field | Type | Description |
|-------|------|-------------|
| `publishId` | `string` | Identifier of the publish attempt – use this to poll status |
| `status` | `string` | Always `queued` on the initial response |
| `deploymentId` | `string \| null` | Deployment identifier, when the build already has one |
| `deploymentUrl` | `string \| null` | Preview URL for the deployment |
| `inspectorUrl` | `string \| null` | Vercel inspector URL for build details |
| `savedChanges` | `boolean` | Whether uncommitted design-workspace work was saved by this publish |

Poll with `publishId`. A publish is followed by its own identifier whichever machine builds the store, so `deploymentId`, `deploymentUrl` and `inspectorUrl` are informational only and can be `null` until the build has a deployment.

### Errors

| Status | Description |
|--------|-------------|
| `400` | Store does not have a platform-managed deployment |
| `403` | Publishing requires the store API key (OAuth tokens are rejected) |
| `409` | Can't publish right now – a publish is already running, or the store's design workspace isn't up. Retry once it clears. |

---

## Get Publish Status

```
GET /api/v1/publish/:publishId
```

Returns the current state of a publish started via `POST /api/v1/publish`. Only publishes belonging to the authenticated store are visible.

### Path Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `publishId` | `string` | The `publishId` returned by `POST /api/v1/publish` |

```bash
curl -H "Authorization: Bearer sk_your_api_key" \
  https://your-store.yns.store/api/v1/publish/0199f0a1-7c3e-7a21-9f2d-6b1f0c4a8e55
```

### Response (200)

```json
{
  "publishId": "0199f0a1-7c3e-7a21-9f2d-6b1f0c4a8e55",
  "status": "building",
  "readyState": "BUILDING",
  "deploymentId": "dpl_abc123",
  "url": "store-abc123.vercel.app",
  "commitSha": "3f1c9a0d8b7e6f5a4c3b2a1908f7e6d5c4b3a291",
  "reason": null
}
```

| Field | Type | Description |
|-------|------|-------------|
| `publishId` | `string` | The publish being reported on |
| `status` | `string` | Where the publish is (see below) |
| `readyState` | `string` | The build's own state, for callers written against the deployment contract |
| `deploymentId` | `string \| null` | Deployment identifier, `null` until the build has one |
| `url` | `string \| null` | Deployment URL |
| `commitSha` | `string \| null` | Commit the publish ships |
| `reason` | `string \| null` | Plain-language explanation, set on `domain_pending` and `failed` |

### Publish Statuses

| Status | Terminal | Description |
|--------|----------|-------------|
| `queued` | no | Claimed, waiting for a build to start |
| `building` | no | Build is running |
| `verifying` | no | Build finished; the platform is verifying the commit before pinning domains |
| `live` | yes | The store's domains serve the new build |
| `domain_pending` | yes | The build shipped, but a domain is not serving it yet – see `reason` |
| `failed` | yes | The publish did not ship – see `reason` |

Poll until `status` is terminal. A `readyState` of `READY` only means the build finished; `live` is the one status that means the publish is serving.

### Errors

| Status | Description |
|--------|-------------|
| `400` | Store does not have a platform-managed deployment |
| `404` | No such publish for this store, or a newer publish replaced it (only the running publish and the latest verdict are kept) |

---

## Get Deployment Status (legacy)

```
GET /api/v1/publish/:deploymentIdOrUrl
```

The same path also accepts a Vercel deployment id (`dpl_...`) or hostname, for callers written before publish ids existed. It answers with the deployment alone, which says nothing about whether domains were promoted – prefer polling by `publishId`.

```bash
curl -H "Authorization: Bearer sk_your_api_key" \
  https://your-store.yns.store/api/v1/publish/dpl_abc123
```

### Response (200)

```json
{
  "id": "dpl_abc123",
  "url": "store-abc123.vercel.app",
  "readyState": "BUILDING"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `id` | `string` | Deployment identifier |
| `url` | `string \| null` | Deployment URL |
| `readyState` | `string` | Current state of the deployment |

### Ready States

| State | Description |
|-------|-------------|
| `QUEUED` | Deployment is queued and waiting to start |
| `BUILDING` | Build is in progress |
| `INITIALIZING` | Build finished, deployment is initializing |
| `READY` | Build is live on the deployment URL (terminal) |
| `ERROR` | Build or deployment failed (terminal) |
| `CANCELED` | Deployment was canceled (terminal) |

### Errors

| Status | Description |
|--------|-------------|
| `400` | Store does not have a platform-managed deployment |
| `404` | Deployment not found or does not belong to this store |