API Reference
Technical reference for OpsPilot's API endpoints, authentication, webhooks, plan limits, and system behavior for developers and store administrators.
Shopify webhook topics, event routing, and how workflows are triggered behind the scenes.
OAuth 2.0 flow, session management, Shopify API rate limits, and plan-based quotas.
Authentication & Installation
OAuth 2.0 Flow
OpsPilot uses Shopify's standard OAuth 2.0 for authentication. The flow on install:
/auth/login with their shop domain/auth/*; session created with: shop, accessToken, userId, scope, email, firstName, lastName, accountOwner/app/dashboardRequired Shopify Scopes
| Scope | Purpose |
|---|---|
read_checkouts | Checkout Abandoned trigger |
read_customers | Customer Created trigger, customer data in variables |
read_inventory | Inventory Level Updated trigger, inventory KPIs |
read_orders | Order Created/Updated triggers, order data in variables |
read_products | Product Updated trigger, product data in variables |
API Endpoints
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/api/scheduled-workflows | POST | QSTASH signing key or CRON_SECRET Bearer token | Trigger scheduled and delayed workflow execution |
/api/item-actions | POST | CORS (Shopify admin surface) | Create tasks and notes from Shopify order/product/customer pages via the app extension |
/health | GET | None | Health check — returns 200 OK if the service is running |
/ready | GET | None | Readiness probe — used by infrastructure to confirm the app is ready to serve traffic |
/webhooks | POST | Shopify HMAC signature | Generic Shopify webhook receiver — routes to appropriate handler by topic |
/webhooks/app/scopes_update | POST | Shopify HMAC | Registered but not yet implemented — scope changes do not trigger any action |
/webhooks/app/uninstalled | POST | Shopify HMAC | App uninstall webhook — removes all sessions for the shop |
/api/scheduled-workflows
Triggers the scheduled workflow runner. Called by a cron job or queue service (e.g., QStash). Supports three execution modes:
| Mode | Description |
|---|---|
scheduled | Run all workflows whose cron schedule matches the current time |
delayed | Execute all delayed actions whose executeAfter timestamp has passed |
all | Run both scheduled and delayed |
/api/item-actions
Allows the Shopify Admin app extension to create tasks and notes directly from order, product, and customer pages inside Shopify. Uses CORS authentication tied to the Shopify admin surface.
Shopify Webhooks
OpsPilot registers the following Shopify webhook topics on installation:
| Webhook Topic | OpsPilot Trigger | Notes |
|---|---|---|
orders/create | Order Created | Fires when any new order is placed |
orders/updated | Order Updated | Fires on status, tag, or fulfillment changes |
checkouts/delete | Checkout Abandoned | Fires when a checkout is abandoned |
inventory_levels/update | Inventory Level Updated | Fires when inventory quantity changes for a variant |
customers/create | Customer Created | Fires when a new customer account is created |
products/update | Product Updated | Fires when any product field is modified |
app/uninstalled | App Uninstall | Deletes all sessions for the shop |
app/scopes_update | — | Registered but not yet handled |
Plan Limits
| Feature | FREE | STARTER | GROWTH |
|---|---|---|---|
| Active workflows | 1 | 5 | 20 |
| Workflow runs / month | Low (env-configurable) | 500 | 5,000 |
| Actions per workflow | 2 | 10 | 20 |
| Email action | ✗ | ✓ | ✓ |
| Slack action | ✗ | ✓ | ✓ |
| Google Sheets action | ✗ | ✓ | ✓ |
| Analytics dashboard | ✗ | ✓ | ✓ |
New shops automatically receive a 14-day STARTER trial on first install (if not previously used). After the trial, the plan reverts to FREE unless a subscription is active. Plan limits are enforced on every workflow execution — runs over the monthly limit are SKIPPED.
Edge Cases & Special Flows
Workflow Execution Edge Cases
| Scenario | Behavior |
|---|---|
| Payload is not a valid object | Workflow SKIPPED with warning |
| Condition schema invalid | Workflow FAILED ("Invalid workflow definition") |
| Monthly run limit exceeded | Workflow SKIPPED — checked before conditions |
| No active users in shop | Execution halted with error |
| Recursive workflow depth > 2 | Workflow SKIPPED with warning |
| All actions filtered by plan/setup | Workflow SKIPPED (not FAILED) |
| Payload >50KB | Truncated to summary (_truncated: true) |
| Delayed workflow — workflow deleted/disabled before execution | Action SKIPPED |
| Delayed workflow — conditions no longer match at execution time | Action SKIPPED |
| Nested delay (delay within a delayed action) | Re-queued action SKIPPED |
| Concurrent delayed action workers | Atomic row claim prevents double-processing |
| CREATE_ONCE_PER_ENTITY + entity in closed status | New task created instead of updating |
| 24h dedup — same fingerprint detected | Action SKIPPED unless forceExecuteDuplicates: true |
| Aggregate scheduled workflow | One task per entity; entity ID = workflow-aggregate:${workflowId} |
Auth & Installation Edge Cases
| Scenario | Behavior |
|---|---|
| App already installed — user re-opens | Existing session reused; no new OAuth flow |
| Uninstall webhook fires multiple times | Safe — checks if session exists before deleting |
| User re-opens app after uninstall | Full OAuth flow restarts |
| Trial already used on previous install | No auto-trial on re-install |
| Multiple paid Shopify subscriptions | Highest tier wins |
| Paid plan in DB but no active Shopify subscription | Triggers immediate downgrade |
| Upgrade before scheduled downgrade date | Cancels the scheduled downgrade |
Email Domain Edge Cases
| Scenario | Behavior |
|---|---|
| Domain already claimed by another shop | Error returned with owning shop's domain |
| Race condition on domain claim (P2002) | Re-queried to report actual owner |
| Domain removed while sender email uses it | Sender email auto-cleared |
| Domain status stored as "error" | Normalized to "pending" in UI |
| Legacy shop (created before domain locking) | Auto-claims used domains via legacy backfill |
Task Edge Cases
| Scenario | Behavior |
|---|---|
| Empty or whitespace-only title | Rejected |
| Due date in the past | Rejected |
| Assigned user inactive or from different shop | Rejected |
| Bulk delete by non-admin | Rejected |
| Auto-archive unit not days or weeks | Ignored — no archive performed |
| Task notes on delete | Soft-deleted, not hard-deleted |
Onboarding Behavior
On first install, OpsPilot automatically:
- Seeds two onboarding tasks: "Connect Slack and Google Sheets" (HIGH) and "Set up email sender and branding" (MEDIUM) — these use unique markers to prevent duplicates on re-install
- Creates a welcome note (marker:
onboarding:welcome-note:v1) - Auto-starts a 14-day STARTER trial if
billingTrialUsed === false - Auto-opens the onboarding drawer if: no active workflows AND no non-onboarding open tasks