> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pcnaid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Safe Bulk API reference

> Externally reachable API surface including health, onboarding, projects, imports, change sets, playbooks, jobs, staff roles, billing, and privacy exports.

# Safe Bulk API reference

## Base URL

The API is served from the Worker's application origin under the `/api` prefix. All authenticated endpoints require a Shopify App Bridge bearer token in the `Authorization` header.

## Health check

```
GET /health
```

Returns app identity, build SHA, and billing configuration status.

Response: `{"ok":true,"app":"safe-bulk","commit":"...","billingConfigured":true}`

## Onboarding

```
GET /api/onboarding
```

Returns workspace and subscription status.

```
POST /api/onboarding/bootstrap
```

Seeds the workspace and claims the first administrator. Accepts `{}`. Returns admin status and next route.

## Setup

```
GET /api/setup-status
```

Returns the Dashboard follow-up checklist (`Create a product change set`, `Run a change with undo protection`, and `Enable a recurring playbook`), each step's completion and blocked state, and the next unblocked step key. This checklist is separate from the **Setup** page, which covers the workspace and first administrator, subscription access, and an initial reviewed change set. Administrators also receive a `canManageSetup` flag.

```
POST /api/setup-status/skip
```

Administrators only. Accepts `{}`. Dismisses setup for the current installation.

## UI context

```
GET /api/ui-context
```

Returns the authenticated shop domain and, when available, the primary custom domain. Used for presentation metadata.

## Dashboard

```
GET /api/dashboard
```

Returns aggregate metrics: change set count, awaiting-approval count, active job count, and average risk over the last 30 days.

## Projects

```
GET /api/projects
```

Lists all projects for the authenticated shop, ordered by creation date descending.

```
POST /api/projects
```

Creates a new project. Requires `project:create` action. Body:

```json theme={null}
{
  "name": "Project name",
  "entityType": "products",
  "metadata": {}
}
```

`entityType` accepts: `products`, `customers`, `companies`, `metafields`, `metaobjects`.

```
POST /api/projects/:id/archive
```

Archives an active project. Requires `project:archive` action.

## CSV imports

```
POST /api/imports/csv
```

Enqueues a durable CSV import job. Requires `csv:import` action. Body:

```json theme={null}
{
  "name": "Product update",
  "entityType": "products",
  "filename": "products.csv",
  "projectId": null,
  "csv": "handle,title,tags_add,price\n..."
}
```

Returns HTTP 202 with `jobId`, `changeSetId`, and `status: "queued"`. Supports `Idempotency-Key` header. Limits enforced: plan byte and row ceilings.

## Change sets

```
GET /api/change-sets
```

Lists the 100 most recent change sets.

```
GET /api/change-sets/:id?limit=1000&offset=0
```

Returns change-set details, paginated change items, approvals, import status, and item count. `limit` max 5,000.

```
POST /api/change-sets/:id/approval
```

Records an approval or rejection. Requires `change-set:approve` action. Body:

```json theme={null}
{
  "decision": "approved",
  "comment": "Looks good"
}
```

`decision` is `approved` or `rejected`. Returns updated change set and all approvals.

```
POST /api/change-sets/:id/execute
```

Executes an approved change set. Requires `change-set:execute` action. Supports `Idempotency-Key`.

```
POST /api/change-sets/:id/rollback
```

Rolls back an executed change set. Requires `change-set:rollback` action. Supports `Idempotency-Key`.

```
POST /api/change-sets/:id/ai-review
```

Generates an AI review draft. Requires `change-set:ai-review` action. Samples up to 200 items.

## Playbooks

```
GET /api/playbooks
```

Lists all playbooks for the authenticated shop.

```
POST /api/playbooks/vendor-price-adjustment
```

Creates a vendor price adjustment playbook. Requires `playbook:vendor-price-adjustment:create` action.

```json theme={null}
{
  "name": "Vendor price adjustment",
  "projectId": null,
  "vendor": "Acme",
  "percent": 3,
  "intervalMinutes": null,
  "enabled": false
}
```

`percent` range: -90 to 500.

```
POST /api/playbooks/metafield-backfill
```

Creates a metafield backfill playbook. Requires `playbook:metafield-backfill:create` action.

```json theme={null}
{
  "name": "Priority backfill",
  "projectId": null,
  "namespace": "custom",
  "key": "priority",
  "type": "single_line_text_field",
  "value": "standard",
  "query": "",
  "intervalMinutes": null,
  "enabled": false
}
```

```
POST /api/playbooks/tag-governance
```

Creates a tag governance playbook. Requires `playbook:tag-governance:create` action.

```json theme={null}
{
  "name": "Tag governance",
  "projectId": null,
  "query": "",
  "tag": "reviewed",
  "action": "add",
  "intervalMinutes": null,
  "enabled": false
}
```

`action` is `add` or `remove`.

```
POST /api/playbooks/:id/run
```

Runs a playbook immediately. Requires `playbook:run` action. Returns a new change set.

## Jobs

```
GET /api/jobs
```

Lists the 100 most recent execution jobs.

## Staff roles

```
GET /api/staff-roles
```

Lists all staff role assignments. Requires `staff-role:manage` action.

```
PUT /api/staff-roles/:staffId
```

Sets a staff role. Requires `staff-role:manage` action.

```json theme={null}
{
  "role": "operator"
}
```

Roles: `operator`, `approver`, `executor`, `admin`.

```
DELETE /api/staff-roles/:staffId
```

Removes a staff role. Cannot remove your own admin role.

## Privacy exports

```
GET /api/privacy-exports
```

Lists customer data exports. Requires `privacy-export:read` action.

```
GET /api/privacy-exports/:id/download
```

Downloads a customer data export. Requires `privacy-export:read` action.

## Billing

Billing routes are under the `/billing` prefix:

```
GET /billing/status
POST /billing/subscribe
POST /billing/change
POST /billing/cancel
GET /billing/callback
```

`POST /billing/change` and `POST /billing/subscribe` accept `{"plan": "standard"}` or `{"plan": "growth"}`. These redirect to Shopify's billing confirmation page.

## Webhooks

The app registers these Shopify webhook topics:

* `app/uninstalled` — clears credentials for the matching install generation
* `app_subscriptions/update` — projects subscription state into `shops`
* `customers/data_request` — creates an encrypted customer data export
* `customers/redact` — purges customer-linked data
* `shop/redact` — deletes shop data after uninstall

Privacy webhooks are registered via Shopify's `[webhooks.privacy_compliance]` configuration.

[Pcnaid Documentation](https://docs.pcnaid.com/namespace/index.md) › [Shopify Ecosystem](https://docs.pcnaid.com/hubs/shopify-ecosystem/index.md) › [Pcnaid Safe Bulk](https://docs.pcnaid.com/nodes/shopify/safe-bulk/index.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.