Commands
Every change you can make. Run one through its endpoint, preview it with POST /plans or ?preview=true, or from an agent with plan_change. GET /commands lists the ones your key may run, with their JSON schemas. See How changes work for risk levels and approvals.
Subscriptions
Re-check subscriptions against Shopify
subscriptions.reconcile
Re-check every subscription against Shopify and fix anything out of date. Runs in the background; check progress with get_sync_status. Safe to run any time: it only reads from Shopify and updates our copy.
Risk: low · Undo: no · Permission: subscriptions:sync · Who: staff, API keys, agents, built-in agents
Endpoint: POST /api/v1/subscriptions/reconcile
No input.
Skip the next delivery
subscriptions.skip_next
Skip the next delivery. The next charge moves on by one delivery interval (e.g. a month). Good for customers with too much product who'd otherwise cancel.
Risk: low · Undo: yes · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/skip
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
Move the next delivery
subscriptions.reschedule
Move the next delivery to a specific date (tomorrow to a year out). Later deliveries follow on from the new date at the usual interval.
Risk: low · Undo: yes · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/reschedule
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
date | string (date) | Yes | New next delivery date, YYYY-MM-DD in the store's timezone |
Pause a subscription
subscriptions.pause
Pause a subscription: no charges or deliveries until it's resumed.
Risk: medium · Undo: yes · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/pause
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
Resume a subscription
subscriptions.resume
Resume a paused subscription. If its next delivery date has passed, the next delivery is tomorrow at the usual time.
Risk: low · Undo: yes · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/resume
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
Cancel a subscription
subscriptions.cancel
Cancel a subscription. No more charges or deliveries. Record why: it drives which save offers are worth making. Customers can always cancel in one step.
Risk: high · Undo: no · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/cancel
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
reason | too_much · too_expensive · taking_break · not_needed · didnt_like · other | Yes | |
comment | string |
Keep a customer with an offer
subscriptions.accept_save_offer
Take the offer shown to a customer who was about to cancel (skip, deliver later, less often, pause, swap, or a discount) instead of cancelling. Get the offer first with get_save_offer for the customer's reason; only that offer can be accepted. Recorded as a save in the retention report.
Risk: medium · Undo: no · Permission: subscriptions:write · Who: customers, customers' agents, staff, agents, API keys
Endpoint: POST /api/v1/subscriptions/:subscriptionId/save
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
reason | too_much · too_expensive · taking_break · not_needed · didnt_like · other | Yes | |
offer | skip · later · less_often · pause · swap · discount | Yes | The offer's kind, from get_save_offer |
variantId | string (starts_with) | For swap: the variant chosen |
Email a card update link
subscriptions.send_payment_update
Email the customer a secure Shopify link to update the card on this subscription. Use it after a declined or expired card, or when a customer asks. At most once an hour per subscription.
Risk: low · Undo: no · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/payment-update
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
Change a quantity
subscriptions.change_quantity
Change how many of an item come in each delivery. The price per item stays the same; the charge changes with the quantity.
Risk: low · Undo: yes · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/quantity
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
lineId | string | Which line (our line id or the Shopify line GID). Optional when there's only one. | |
quantity | integer (1–99) | Yes | How many of this item in each delivery |
Change how often it delivers
subscriptions.change_frequency
Change how often deliveries come, to another frequency on the same offer (e.g. every 4 weeks instead of every 2). The next charge date stays; later ones follow the new frequency.
Risk: low · Undo: yes · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/frequency
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
every | integer (1–52) | Yes | Deliver every N intervals |
interval | DAY · WEEK · MONTH · YEAR | Yes |
Swap to another variant
subscriptions.swap_variant
Switch an item to another variant of the same product (size, flavour, grind). The subscription discount carries over to the new variant's price.
Risk: low · Undo: yes · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/variant
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
lineId | string | Which line (our line id or the Shopify line GID). Optional when there's only one. | |
variantId | string (starts_with) | Yes | Another variant of the same product |
Change the shipping address
subscriptions.change_address
Ship future deliveries to a new address. The shipping price and method stay as they are, and Shopify refuses an address the store doesn't ship to. The address isn't kept in the activity log.
Risk: low · Undo: no · Permission: subscriptions:write · Who: staff, API keys, agents, built-in agents, customers
Endpoint: POST /api/v1/subscriptions/:subscriptionId/address
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | Our subscription id, or the Shopify contract GID |
address | object | Yes | Where future deliveries should go |
address.firstName | string | ||
address.lastName | string | ||
address.company | string | ||
address.address1 | string | Yes | |
address.address2 | string | ||
address.city | string | Yes | |
address.provinceCode | string | Province or state code, e.g. ON or CA | |
address.countryCode | string | Yes | Two-letter country code, e.g. CA |
address.zip | string | ||
address.phone | string |
Offers
Create an offer
offers.create
Offer subscriptions on products: a name, one or more delivery frequencies, and an optional discount. Shoppers see it on the product page and choose a frequency at checkout.
Risk: medium · Undo: yes · Permission: offers:write · Who: staff, API keys, agents, built-in agents
Endpoint: POST /api/v1/offers
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Shown to shoppers, e.g. "Subscribe & save" |
description | string | ||
frequencies | object[] | Yes | Delivery options shoppers can choose from |
discount | any | Yes | Applied to every subscription order; null for no discount |
productIds | string (starts_with)[] | Yes |
Change an offer
offers.update
Change an offer's name, description, delivery frequencies, discount or products. Existing subscriptions keep the terms they started with; changes apply to new subscriptions.
Risk: medium · Undo: yes · Permission: offers:write · Who: staff, API keys, agents, built-in agents
Endpoint: PATCH /api/v1/offers/:id
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
name | string | ||
description | string | ||
frequencies | object[] | ||
discount | any | ||
productIds | string (starts_with)[] | The full set of products; replaces the current set |
Stop offering a subscription
offers.delete
Stop offering a subscription option. It disappears from product pages. Existing subscriptions keep running on the terms they started with.
Risk: high · Undo: no · Permission: offers:write · Who: staff, API keys, agents, built-in agents
Endpoint: DELETE /api/v1/offers/:id
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes |
Billing
Retry a failed payment now
billing.retry_now
Retry a failed charge now instead of waiting for the next scheduled retry, e.g. after the customer says they've updated their card. Charges the customer's payment method.
Risk: financial · Undo: no · Permission: billing:write · Who: staff, API keys, agents, built-in agents
Endpoint: POST /api/v1/billing/cycles/:cycleId/retry
| Field | Type | Required | Description |
|---|---|---|---|
cycleId | string | Yes |
Imports
Upload subscriptions to import
imports.create
Upload a subscriptions export from another app (Recharge, Skio, Appstle, Loop, Seal, Shopify Subscriptions or a spreadsheet). Nothing is created yet: each subscription is checked against the store (customer, saved card, products, date) in the background. Read the import to see what's ready and what needs fixing, then run imports.start.
Risk: low · Undo: no · Permission: imports:write · Who: staff, API keys, agents
Endpoint: POST /api/v1/imports
| Field | Type | Required | Description |
|---|---|---|---|
csv | string | Yes | The export from the other app, as CSV text, header row first |
filename | string | ||
source | recharge · skio · appstle · loop · seal · shopify · other | Which app it came from. Guessed from the columns when left out. |
Create the imported subscriptions
imports.start
Create the import's ready subscriptions in Shopify, keeping each one's next charge date, price and schedule. They're created in the background, one at a time. They don't bill until imports.release_billing, so the old app has time to be switched off. Subscriptions with problems are left out.
Risk: medium · Undo: no · Permission: imports:write · Who: staff, API keys, agents
Endpoint: POST /api/v1/imports/:importId/start
| Field | Type | Required | Description |
|---|---|---|---|
importId | string | Yes | The import's id, from imports.create |
limit | integer (1–100000) | Import only this many (e.g. 10) to check them in Shopify first. The rest stay ready. |
Start billing imported subscriptions
imports.release_billing
Start billing an import's subscriptions here. Run it only once the old app has stopped charging them (turned off or uninstalled), or customers will be charged twice. Any whose charge date passed while waiting move to their next date, since the old app charged them.
Risk: high · Undo: no · Permission: imports:write · Who: staff, API keys, agents
Endpoint: POST /api/v1/imports/:importId/release-billing
| Field | Type | Required | Description |
|---|---|---|---|
importId | string | Yes | The import's id, from imports.create |
Throw away an import
imports.discard
Throw away an import that hasn't created anything yet, e.g. to upload a corrected file. Imports that have created subscriptions can't be discarded.
Risk: low · Undo: no · Permission: imports:write · Who: staff, API keys, agents
Endpoint: DELETE /api/v1/imports/:importId
| Field | Type | Required | Description |
|---|---|---|---|
importId | string | Yes | The import's id, from imports.create |
Connect Recharge
imports.connect
Connect the app the store is moving from with an API token from it, so subscriptions (and cards held at Stripe, Braintree or Authorize.net) can be fetched directly, and cancelled there when billing switches over. For Recharge the token needs: read_subscriptions, read_customers, read_payment_methods, write_subscriptions. The token is stored encrypted and never shown again.
Risk: medium · Undo: no · Permission: imports:write · Who: staff, API keys
Endpoint: POST /api/v1/imports/connections
Contains a secret (token), so it's hidden in the activity log and can't wait as a plan.
| Field | Type | Required | Description |
|---|---|---|---|
source | recharge | Yes | The app to connect. Recharge for now. |
token | string | Yes | An API token created in that app |
Disconnect Recharge
imports.disconnect
Remove the stored API token for the app the store moved from. Delete the token in that app too.
Risk: low · Undo: no · Permission: imports:write · Who: staff, API keys, agents
Endpoint: DELETE /api/v1/imports/connections/:source
| Field | Type | Required | Description |
|---|---|---|---|
source | recharge | Yes |
Fetch subscriptions from Recharge
imports.fetch
Fetch every active subscription from the connected app (Recharge) and check them against the store, like an upload but always current. Nothing is created yet. Read the import, then run imports.start.
Risk: low · Undo: no · Permission: imports:write · Who: staff, API keys, agents
Endpoint: POST /api/v1/imports/connections/:source/fetch
| Field | Type | Required | Description |
|---|---|---|---|
source | recharge | Yes |
Integrations
Connect Klaviyo
integrations.connect_klaviyo
Send subscription events (started, cancelled, upcoming charge, order placed, payment failed...) to the store's Klaviyo account, for its own flows. The private API key needs: Accounts: Read, Events: Full, Profiles: Full.
Risk: medium · Undo: no · Permission: integrations:write · Who: staff, API keys
Endpoint: POST /api/v1/integrations/klaviyo
Contains a secret (apiKey), so it's hidden in the activity log and can't wait as a plan.
| Field | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | A Klaviyo private API key (pk_...) |
Disconnect Klaviyo
integrations.disconnect_klaviyo
Stop sending subscription events to Klaviyo and remove the stored key.
Risk: low · Undo: no · Permission: integrations:write · Who: staff, API keys, agents
Endpoint: DELETE /api/v1/integrations/klaviyo
No input.
Store
Change store settings
shop.update_settings
Change store-wide subscription settings: sender name, support email, the failed-payment retry schedule, what happens after the final retry, and which customer emails are sent. Only the fields you pass change.
Risk: medium · Undo: yes · Permission: settings:write · Who: staff, API keys, agents, built-in agents
Endpoint: PATCH /api/v1/settings
| Field | Type | Required | Description |
|---|---|---|---|
senderName | string | Name shown on subscriber emails and texts. | |
supportEmail | string (email) | Where subscriber replies go. null to use the store's contact email. | |
accountPageUrl | string (uri) | The store's Subscriptions page in customer accounts, copied from the checkout and accounts editor. Customer emails and links go there. null to use the customer account home. | |
dunningRetryDays | integer[] | Days after a failed charge to retry it, in order. | |
afterFinalRetry | pause · cancel | What happens to a subscription when every retry has failed. | |
billingPaused | boolean | Stop all new charges for this store. Charges already sent still finish. | |
notices | object | Which customer emails Usual sends. Turn off any you'd rather send yourself. | |
notices.confirmation | boolean | Yes | Email subscribers their terms and how to cancel when they sign up. |
notices.upcomingCharge | boolean | Yes | Remind subscribers before each renewal charge. |
notices.upcomingChargeDays | integer (1–14) | Yes | How many days before a charge to remind them. |
notices.paymentFailed | boolean | Yes | Tell subscribers when a renewal payment fails. |
notices.cancelled | boolean | Yes | Confirm cancellations by email. |
retention | object | What customers are offered when they go to cancel. | |
retention.offers | object | Yes | Which offers customers can see when they cancel. One fits their reason; cancelling stays one click. |
retention.offers.skip | boolean | Yes | Skip the next delivery instead. |
retention.offers.later | boolean | Yes | Get the next delivery two weeks later. |
retention.offers.lessOften | boolean | Yes | Switch to a less frequent schedule from the subscription's offer. |
retention.offers.pause | boolean | Yes | Pause until they resume. |
retention.offers.swap | boolean | Yes | Swap to another option of the same product. |
retention.offers.discount | boolean | Yes | A discount on the next few deliveries. |
retention.discountPercent | integer (5–50) | Yes | The discount, in percent. |
retention.discountDeliveries | integer (1–6) | Yes | How many deliveries the discount lasts. |
Keys
Create a key
api_client.create
Create an API key or agent credential. The token is returned once and never shown again.
Risk: high · Undo: no · Permission: * · Who: staff
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | |
kind | api_key · agent | Yes | agent: an AI agent. Its writes always need a preview first, and riskier ones need approval. |
scopes | settings:read · settings:write · audit:read · subscriptions:read · subscriptions:write · subscriptions:sync · offers:read · offers:write · billing:read · billing:write · imports:read · imports:write · integrations:write[] | Yes |
Revoke a key
api_client.revoke
Revoke an API key or agent credential. It stops working immediately.
Risk: high · Undo: no · Permission: * · Who: staff
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes |