Skip to content

SLO API

Build against the canonical SLO REST API, then use the agent endpoint when tool-call semantics are a better fit. Both surfaces share the same underlying application logic.

What can you do with it?

The REST API under /api/* is the long-term contract for shop automation and integrations. The agent endpoint is an adapter for tool-based clients, not a separate business-logic surface.

Products

Create, update, and remove products. Set prices, descriptions, and inventory — all at once or one at a time.

Drops

Set up new drops with dates, channels, and products. Open and close them when you're ready.

Orders

See incoming orders, confirm or cancel them, update fulfillment status as you pack and deliver.

Inventory

Update stock levels globally or per channel. Keep availability in sync without manual entry.

Channels

List your sales channels — delivery, pickup, wholesale — and manage which ones are active.

Start with REST when you want stable resource-oriented contracts. Use the agent endpoint when you want the same capabilities exposed as tool calls.

Quick start

1

Get an API key

Shop admin → Apps → Create Key. Copy it — shown once.

2

Call the canonical REST API

curl -X GET 'https://slo.earth/api/channels?shopId=shop_123' \
  -H "Authorization: Bearer sk_live_..."
3

Use the agent adapter when needed

curl -X POST https://slo.earth/api/agent \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"tool":"listProducts"}'
4

Get structured data back

{
  "ok": true,
  "result": {
    "products": [...],
    "total": 12
  }
}

Endpoints

Canonical REST API
GET/POST https://slo.earth/api/*

Agent adapter
POST https://slo.earth/api/agent

Authorization: Bearer sk_live_...

REST example

GET /api/channels?shopId=shop_123

POST /api/channels
{
  "action": "create",
  "shopId": "shop_123",
  "title": "Wholesale"
}

Agent example

POST /api/agent
{
  "tool": "createChannel",
  "params": { "title": "Wholesale" }
}

Mutation response

{
  "success": true,
  "requestId": "req_123",
  "replayed": false
}

Error

{
  "error": "Forbidden",
  "requestId": "req_123"
}

Authentication

Use a bearer token in the Authorization header. Each key is scoped to one shop and can be revoked at any time. For mutating requests, you can also send Idempotency-Key and X-Request-Id.

Authorization: Bearer sk_live_your_key_here
Idempotency-Key: optional-but-recommended-for-mutations
X-Request-Id: optional-client-request-id

Tools

products

listProducts

List products for your shop. Use the 'search' param to filter by name/variety when looking for specific products — avoids returning the full catalog.

Params

limitnumberMax products to return
offsetnumberNumber of products to skip
searchstringFilter by title or variety (case-insensitive)
{
  "tool": "listProducts",
  "params": {}
}

{ products: Product[], total: number }

getProduct

Get a single product by ID

Params

productIdstringrequiredThe product _id
{
  "tool": "getProduct",
  "params": {
    "productId": "product_abc123"
  }
}

{ product: Product }

createProduct

Create a new product

Params

titlestringrequiredProduct title
descriptionstringProduct description
pricenumberBase price per kg/L/piece in SEK (NOT per selling unit — the system calculates per-unit price)
inventoryTypestringHow inventory is tracked: "weight" (bulk kg), "volume" (bulk L), or "piece" (counted items). Default: weight
unitTypestringWhat the customer buys: "weight", "volume", or "item". For bulk: matches inventoryType. For pre-packaged: "piece" inventory + "weight"/"volume" unitType
unitnumberSelling unit size in g/mL. Default 1000 (=1kg or 1L). Examples: 10000 for 10kg batch, 500 for 500g bag
unitStepnumberMinimum order increment. For bulk weight/volume: 0.1 = customer can order in 100g/100mL steps. For piece: 1 = one at a time
varietystringProduct variety/cultivar (e.g. "King Edward", "Roma")
hideFromStorefrontbooleanHide from public storefront
taxnumberTax rate as decimal (e.g. 0.12 for 12%)
hideFromCalendarbooleanHide from harvest calendar
transportCategorystringTemperature zone for delivery: "frozen", "refrigerated", or "roomTemperature" (default)
{
  "tool": "createProduct",
  "params": {
    "title": "Organic Tomatoes"
  }
}

{ product: Product }

updateProduct

Update an existing product. Only send fields you want to change.

Params

productIdstringrequiredThe product _id
titlestringProduct title
varietystringProduct variety/cultivar (e.g. "King Edward", "Roma")
descriptionstringProduct description
pricenumberBase price per kg/L/piece in SEK (NOT per selling unit — the system calculates per-unit price)
inventoryTypestringHow inventory is tracked: "weight" (bulk kg), "volume" (bulk L), or "piece" (counted items)
unitTypestringWhat the customer buys: "weight", "volume", or "item". For bulk: matches inventoryType. For pre-packaged: "piece" inventory + "weight"/"volume" unitType
unitnumberSelling unit size in g/mL. Examples: 10000 for 10kg batch, 500 for 500g bag, 1000 for 1kg/1L
unitStepnumberMinimum order increment. For bulk weight/volume: 0.1 = 100g/100mL steps. For piece: 1 = one at a time
hideFromStorefrontbooleanHide from public storefront
taxnumberTax rate as decimal (e.g. 0.12 for 12%)
hideFromCalendarbooleanHide from harvest calendar
channelPricesstringJSON array of channel price overrides, e.g. [{"channelId":"abc","price":50}]
channelInventorystringJSON array of channel inventory overrides, e.g. [{"channelId":"abc","available":10}]
channelUnitsstringJSON array of channel unit overrides, e.g. [{"channelId":"abc","unit":500,"unitStep":0.1}]
harvestStartstringHarvest start date (YYYY-MM-DD)
harvestEndstringHarvest end date (YYYY-MM-DD)
transportCategorystringTemperature zone for delivery: "frozen", "refrigerated", or "roomTemperature" (default)
{
  "tool": "updateProduct",
  "params": {
    "productId": "product_abc123"
  }
}

{ product: Product }

batchUpdateProducts

Update multiple products at once. Send a JSON array of updates as a string.

Params

updatesstringrequiredJSON array of objects, each with productId and fields to update. Example: [{"productId":"abc","price":200},{"productId":"def","title":"New name"}]
{
  "tool": "batchUpdateProducts",
  "params": {
    "updates": "..."
  }
}

{ results: { productId, ok, title?, error? }[] }

deleteProduct

Delete a product

Params

productIdstringrequiredThe product _id
{
  "tool": "deleteProduct",
  "params": {
    "productId": "product_abc123"
  }
}

{ deleted: true }

uploadProductImage

Set a product's primary image. IMPORTANT: When the user has attached an image in chat, ALWAYS use assetId from the attachment metadata — NEVER use imageBase64. The assetId is shown in the attachment info like 'Sanity asset ID: image-xxx'. Only use imageUrl for external URLs. Never generate or fabricate base64 data.

Params

productIdstringrequiredThe product _id
assetIdstringSanity asset ID (e.g. 'image-abc123-1920x1080-jpg') from a user-uploaded attachment. Preferred when available.
imageUrlstringPublic HTTPS URL of the image
imageBase64stringBase64-encoded image data (e.g. from a user-uploaded file)
mimeTypestringMIME type when using imageBase64 (e.g. "image/png", "image/jpeg"). Defaults to image/png.
{
  "tool": "uploadProductImage",
  "params": {
    "productId": "product_abc123"
  }
}

{ success: boolean, assetRef: string, productId: string }

inventory

updateInventory

Update inventory for a product (global or per-channel)

Params

productIdstringrequiredThe product _id
availablenumberAvailable stock in display units: kg for weight, L for volume, count for piece (e.g. pass 2 for 2 kg, not 2000)
channelIdstringOptional: update channel-specific inventory instead of global
{
  "tool": "updateInventory",
  "params": {
    "productId": "product_abc123"
  }
}

{ product: Product }

batchUpdateInventory

Update inventory for multiple products in one call. More efficient than calling updateInventory multiple times.

Params

updatesstringrequiredJSON array: [{"productId":"...","available":10},{"productId":"...","available":25}]. Values in display units (kg/L/count).
{
  "tool": "batchUpdateInventory",
  "params": {
    "updates": "..."
  }
}

{ results: { productId, title, variety, previousAvailable, newAvailable, unit, imageUrl }[] }

drops

listDrops

List drops for your shop

Params

statusstringFilter: "draft" (isDraft=true), "active" (on sale now: dropStart<=now<=dropEnd, not draft), "closed" (dropEnd in past). No filter = all drops.
limitnumberMax drops to return
{
  "tool": "listDrops",
  "params": {}
}

{ drops: Drop[] }

getDrop

Get a single drop by ID

Params

dropIdstringrequiredThe drop _id
{
  "tool": "getDrop",
  "params": {
    "dropId": "drop_abc123"
  }
}

{ drop: Drop }

createDrop

Create a new drop (scheduled product release). Only channelIds + deliveryStart are required. Missing dates get smart defaults at publish: dropStart=now, dropEnd=deliveryStart-3h, deliveryEnd=deliveryStart+3h. If deliveryStart is provided, auto-publishes.

Params

channelIdsarrayrequiredArray of channel _ids to publish to
deliveryStartstringDelivery/pickup window starts — ISO 8601 datetime. Required for auto-publish.
descriptionstringDrop description
dropStartstringOrder window opens — ISO 8601 datetime. Default: now (publish time)
dropEndstringOrder window closes — ISO 8601 datetime. Default: deliveryStart - 3h
deliveryEndstringDelivery/pickup window ends — ISO 8601 datetime. Default: deliveryStart + 3h
deliveryPickupstringWhen the driver picks up packed orders from the shop (delivery channels only). Private — only admin and driver see this. ISO 8601 datetime, between dropEnd and deliveryStart. User may say: 'driver comes at 10', 'pickup at 8', 'hämtning kl 9', 'picked up Wednesday morning'. Defaults to dropEnd if not provided.
quotanumberMaximum total orders for this drop
{
  "tool": "createDrop",
  "params": {
    "channelIds": [
      "channel_abc123"
    ]
  }
}

{ drop: Drop }

updateDrop

Update an existing drop. Only send fields you want to change.

Params

dropIdstringrequiredThe drop _id
descriptionstringDrop description
dropStartstringOrder window opens — ISO 8601 datetime
dropEndstringOrder window closes — ISO 8601 datetime
deliveryStartstringDelivery/pickup window starts — ISO 8601 datetime
deliveryEndstringDelivery/pickup window ends — ISO 8601 datetime
deliveryPickupstringWhen the driver picks up packed orders from the shop (delivery channels only). Private — only admin and driver see this. ISO 8601 datetime, between dropEnd and deliveryStart. User may say: 'driver comes at 10', 'pickup at 8', 'hämtning kl 9', 'picked up Wednesday morning'.
quotanumberMaximum total orders for this drop
isDraftbooleanSet to false to publish (make visible to buyers), true to draft (hide). Use publishDrop/setDropDraft for standalone status changes.
{
  "tool": "updateDrop",
  "params": {
    "dropId": "drop_abc123"
  }
}

{ drop: Drop }

deleteDrop

Delete a drop. Fails if the drop has associated orders.

Params

dropIdstringrequiredThe drop _id
{
  "tool": "deleteDrop",
  "params": {
    "dropId": "drop_abc123"
  }
}

{ deleted: true }

addProductsToDrop

Add products to an existing drop (appends, does not replace)

Params

dropIdstringrequiredThe drop _id
productsarrayrequiredArray of { productId, quota? } to add
{
  "tool": "addProductsToDrop",
  "params": {
    "dropId": "drop_abc123",
    "products": []
  }
}

{ drop: Drop }

removeProductFromDrop

Remove a product from a drop by its _key

Params

dropIdstringrequiredThe drop _id
productKeystringrequiredThe _key of the product entry in the drop
{
  "tool": "removeProductFromDrop",
  "params": {
    "dropId": "drop_abc123",
    "productKey": "..."
  }
}

{ drop: Drop }

publishDrop

Publish a draft drop (makes it visible to buyers). Only deliveryStart is required — missing dates get smart defaults: dropStart=now, dropEnd=deliveryStart-3h, deliveryEnd=deliveryStart+3h.

Params

dropIdstringrequiredThe drop _id
{
  "tool": "publishDrop",
  "params": {
    "dropId": "drop_abc123"
  }
}

{ drop: Drop }

setDropDraft

Set a drop back to draft (hides from buyers)

Params

dropIdstringrequiredThe drop _id
{
  "tool": "setDropDraft",
  "params": {
    "dropId": "drop_abc123"
  }
}

{ drop: Drop }

orders

listOrders

List orders for your shop

Params

dropIdstringFilter by drop _id
statusstringFilter by status
limitnumberMax orders to return (default: 50)
offsetnumberNumber of orders to skip
{
  "tool": "listOrders",
  "params": {}
}

{ orders: Order[], total: number }

getOrder

Get a single order by _id or order number

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
{
  "tool": "getOrder",
  "params": {
    "orderId": "order_abc123"
  }
}

{ order: Order }

updateOrderStatus

Update the status of an order

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
statusstringrequiredNew status (e.g. "confirmed", "delivered", "cancelled")
{
  "tool": "updateOrderStatus",
  "params": {
    "orderId": "order_abc123",
    "status": "active"
  }
}

{ order: Order }

confirmOrder

Confirm a pending order. Sets correct status based on payment type (invoice → confirmedInvoice, swish → paid), sets fulfillment to packing, and notifies the buyer.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "confirmOrder",
  "params": {
    "orderId": "order_abc123"
  }
}

{ order: Order }

cancelOrder

Cancel an order. Refunds inventory and notifies the buyer.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
cancelledBystringWho initiated the cancellation: "buyer" or "seller". Defaults to "seller".
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "cancelOrder",
  "params": {
    "orderId": "order_abc123"
  }
}

{ success: true }

updateFulfillment

Update order fulfillment status. Valid statuses: packing, ready, inTransit, delivered. Notifies the buyer on status change.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
statusstringrequiredNew fulfillment status: packing, ready, inTransit, or delivered
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "updateFulfillment",
  "params": {
    "orderId": "order_abc123",
    "status": "active"
  }
}

{ order: Order }

editOrderItems

Edit item prices/quantities and/or remove items from an existing order. Quantities are in display units. Inventory is auto-adjusted for pending orders.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
editsstringJSON array: [{"itemKey":"...","price":75,"quantity":2}]. Include only fields to change.
removalsstringJSON array of item _key strings to remove: ["key1","key2"]
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "editOrderItems",
  "params": {
    "orderId": "order_abc123"
  }
}

{ order: Order }

addOrderItems

Add one or more products to an existing order. Quantities in display units (kg/L/count). Inventory is auto-adjusted.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
itemsstringrequiredJSON array: [{"productId":"...","quantity":2}]. Quantity in display units.
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "addOrderItems",
  "params": {
    "orderId": "order_abc123",
    "items": "..."
  }
}

{ order: Order }

addOrderItemsFromCart

Append one or more pre-built order items to an existing order. Use this when the items were already constructed by the cart builder.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
itemsarrayrequiredArray of pre-built OrderItem objects to append.
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "addOrderItemsFromCart",
  "params": {
    "orderId": "order_abc123",
    "items": []
  }
}

{ order: Order }

updateDeliveryPrice

Update the delivery/pickup price on an existing order. Pass the new ex-VAT price. Tax summary auto-recalculates.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
deliveryPricenumberrequiredNew delivery price (ex-VAT). Use 0 for free delivery.
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "updateDeliveryPrice",
  "params": {
    "orderId": "order_abc123",
    "deliveryPrice": 10
  }
}

{ order: Order }

reassignOrderDrop

Move an order to a different drop. Updates delivery dates and resets fulfillment. Prices and items stay the same. The new drop must have the same channel as the order.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
dropIdstringrequiredThe new drop _id to move the order to
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "reassignOrderDrop",
  "params": {
    "orderId": "order_abc123",
    "dropId": "drop_abc123"
  }
}

{ success: true }

capturePayment

Capture a Stripe payment for an uncaptured order, mark it paid, and move fulfillment to packing.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
notifyBuyerbooleanSet to false to skip buyer notifications for this action.
{
  "tool": "capturePayment",
  "params": {
    "orderId": "order_abc123"
  }
}

{ order: Order }

cancelPayment

Cancel a Stripe payment and mark the order as cancelled.

Params

orderIdstringrequiredThe order _id or order number (e.g. '97')
{
  "tool": "cancelPayment",
  "params": {
    "orderId": "order_abc123"
  }
}

{ success: true }

createOrder

Create an order. Known buyers (entityId) get a finalized order immediately (inventory overdraft is allowed — the seller already confirmed via estimate). Unknown buyers (email only) get a draft with an invitation. If finalization fails, the order is saved as a visible draft for admin review.

Params

channelIdstringrequiredChannel _id
dropIdstringrequiredDrop _id
itemsstringrequiredJSON array: [{"productId":"...","quantity":2}]. Quantity in display units: kg for weight, L for volume, count for pieces.
entityIdstringBuyer entity _id (known buyer)
emailstringBuyer email — only use when admin explicitly provides it. NEVER fabricate or guess an email. Prefer entityId from listCustomers.
buyerNamestringDisplay name (used in invite flow)
sendInvitationbooleanSend invitation email for unknown buyer (default: false — must be explicitly set to true only after admin confirms)
deliveryPricenumberCustom delivery price (0 for free). Omit for channel default.
draftOnlybooleanSave as draft without finalizing. REQUIRED when creating orders from image/document parsing (handwritten forms, PDFs, Excel). The admin must review and finalize manually.
{
  "tool": "createOrder",
  "params": {
    "channelId": "channel_abc123",
    "dropId": "drop_abc123",
    "items": "..."
  }
}

{ order: { orderId, orderNumber, status }, invitation?: { invitationId } }

estimateOrder

Compute order totals (items + delivery + grand total) without creating an order. Use this to show a breakdown before confirming. Returns stock availability per item — check hasOverstock and warn the user about insufficient inventory before proceeding.

Params

channelIdstringrequiredChannel _id
dropIdstringrequiredDrop _id
itemsstringrequiredJSON array: [{"productId":"...","quantity":2}]. Quantity in display units: kg for weight, L for volume, count for pieces.
entityIdstringBuyer entity _id (for resolving buyer name)
deliveryPricenumberCustom delivery price (0 for free). Omit for channel default.
{
  "tool": "estimateOrder",
  "params": {
    "channelId": "channel_abc123",
    "dropId": "drop_abc123",
    "items": "..."
  }
}

{ estimate: { buyerName, channel, items: [{ ..., availableStock, requestedStock, overstock }], subtotal, delivery, deliveryOverridden, grandTotal, currency, taxType, hasOverstock } }

channels

listChannels

List all channels for your shop

{
  "tool": "listChannels"
}

{ channels: Channel[] }

getChannel

Get a single channel by ID

Params

channelIdstringrequiredThe channel _id
{
  "tool": "getChannel",
  "params": {
    "channelId": "channel_abc123"
  }
}

{ channel: Channel }

createChannel

Create a new sales channel

Params

titlestringrequiredChannel title
privacystring"public" or "private" (default: public)
paymentsstringPayment method: "invoice", "manual_invoice", "swish", or "card"
deliveryTypestring"delivery" or "pickup"
deliveryPricenumberDelivery fee
{
  "tool": "createChannel",
  "params": {
    "title": "Organic Tomatoes"
  }
}

{ channel: Channel }

updateChannel

Update a channel. Only send fields you want to change.

Params

channelIdstringrequiredThe channel _id
titlestringChannel title
privacystring"public" or "private"
paymentsstringPayment method
deliveryTypestring"delivery" or "pickup"
deliveryPricenumberDelivery fee
{
  "tool": "updateChannel",
  "params": {
    "channelId": "channel_abc123"
  }
}

{ channel: Channel }

deleteChannel

Delete a channel. Fails if drops reference this channel.

Params

channelIdstringrequiredThe channel _id
{
  "tool": "deleteChannel",
  "params": {
    "channelId": "channel_abc123"
  }
}

{ deleted: true }

shop

getShop

Get your shop details

{
  "tool": "getShop"
}

{ shop: Shop }

updateShopProfile

Update the shop's public profile. Only send fields you want to change: title, description, contact info, social links, certifications.

Params

titlestringShop title (1-100 chars)
descriptionstringShop description
contactPersonstringContact person name
contactPhonestringContact phone number
contactEmailstringContact email address
instagramstringInstagram URL
facebookstringFacebook URL
websitestringWebsite URL
certDemeterbooleanDemeter certification
certKravbooleanKRAV certification
certOrganicbooleanEU organic certification
certBiosuissebooleanBio Suisse certification
certAbbooleanAB (Agriculture Biologique) certification
certOtherstringOther certification (free text)
{
  "tool": "updateShopProfile",
  "params": {}
}

{ success: true }

updateShopLocalisation

Update shop localisation settings: language, country, currency, tax rate and mode. Only send fields you want to change.

Params

languagestringShop language: 'en' or 'sv'
countrystringCountry code (e.g. 'SE', 'DK')
currencystringCurrency: 'sek', 'dkk', 'eur', or 'usd'
taxnumberDefault tax rate as decimal (e.g. 0.12 for 12%)
taxModestringTax mode: 'manual' or 'country_rules'
{
  "tool": "updateShopLocalisation",
  "params": {}
}

{ success: true, language?: string }

updateShopSlug

Change the shop's URL handle (slo.earth/<handle>). Must be unique, lowercase letters/numbers/hyphens only.

Params

slugstringrequiredNew URL handle (e.g. 'nibble-farm')
{
  "tool": "updateShopSlug",
  "params": {
    "slug": "..."
  }
}

{ success: true, slug: string }

togglePickup

Enable or disable pickup at the shop's physical address.

Params

enabledbooleanrequiredtrue to enable pickup, false to disable
{
  "tool": "togglePickup",
  "params": {
    "enabled": false
  }
}

{ success: true, pickupEnabled: boolean }

updatePhysicalStore

Configure the shop's physical store: opening hours, pickup days, and Google sync. Opening hours is an array of 7 objects (day 0=Monday to 6=Sunday) with open/close times and closed flag.

Params

enabledbooleanrequiredEnable/disable physical store
openingHoursarrayrequiredArray of {day:0-6, open:'HH:MM', close:'HH:MM', closed:boolean}
pickupDaysModestring'openingHours' (default) or 'manual'
pickupDaysarrayArray of day numbers (0-6) for manual pickup days
googleSyncEnabledbooleanEnable Google Maps hours sync
{
  "tool": "updatePhysicalStore",
  "params": {
    "enabled": false,
    "openingHours": []
  }
}

{ success: true }

toggleVacationMode

Enable or disable vacation mode for the shop. When on, the shop appears as on vacation to buyers. Optionally set start and end dates.

Params

vacationModebooleanrequiredtrue to enable vacation, false to disable
vacationStartstringVacation start datetime (ISO format, e.g. '2025-07-01T00:00:00')
vacationEndstringVacation end datetime (ISO format, e.g. '2025-07-14T23:59:59')
{
  "tool": "toggleVacationMode",
  "params": {
    "vacationMode": false
  }
}

{ success: true, vacationMode: boolean }

updateShopColors

Update the shop's brand colors. Only send colors you want to change. Values should be valid CSS color values (hex, rgb, etc.).

Params

bgstringBackground color (e.g. '#ffffff')
fgstringForeground/text color (e.g. '#1a1a1a')
secondarystringSecondary text color
accentstringAccent/brand color
{
  "tool": "updateShopColors",
  "params": {}
}

{ success: true }

updateSwishConfig

Configure Swish payment (Swedish mobile payment). Set the Swish phone number and company name.

Params

phonestringrequiredSwish phone number (Swedish format, e.g. '0701234567' or '1231234567')
companystringrequiredCompany name shown to payers
{
  "tool": "updateSwishConfig",
  "params": {
    "phone": "...",
    "company": "..."
  }
}

{ success: true }

publishShop

Publish or unpublish the shop

Params

publishbooleanrequiredtrue to publish, false to unpublish
{
  "tool": "publishShop",
  "params": {
    "publish": false
  }
}

{ shop: Shop }

customers

listCustomers

List customers (buyers/followers) for your shop. Returns company name and channel membership for each buyer. Searches entity title, org name, and company name.

Params

searchstringSearch by name, company name, or email
limitnumberMax results (default: 50)
{
  "tool": "listCustomers",
  "params": {}
}

{ customers: Customer[] } // Each: { id, displayName, companyName, email, channels: [{_id, title}] }

updateFollowerChannels

Update which channels a buyer has access to

Params

entityIdstringrequiredBuyer entity _id
channelIdsarrayrequiredArray of channel _ids the buyer should have access to
{
  "tool": "updateFollowerChannels",
  "params": {
    "entityId": "...",
    "channelIds": [
      "channel_abc123"
    ]
  }
}

{ updated: true }

inviteBuyer

Invite a buyer to follow your shop. ONLY call this after: 1) confirming the buyer is not already a follower (listCustomers), 2) the admin has provided the email, 3) you have read the email back and the admin confirmed it.

Params

emailstringrequiredBuyer email — must come from the admin, NEVER fabricated or guessed
channelIdsarrayOptional: array of private channel _ids to grant access to
{
  "tool": "inviteBuyer",
  "params": {
    "email": "..."
  }
}

{ invitation: { invitationId } }

notifications

notifyFollowers

Send a push notification to all shop followers

Params

titlestringrequiredNotification title
bodystringrequiredNotification body text
{
  "tool": "notifyFollowers",
  "params": {
    "title": "Organic Tomatoes",
    "body": "..."
  }
}

{ sent: true, count: number }

meta

listTools

List all available API tools and their parameters

{
  "tool": "listTools"
}

{ tools: ToolDefinition[] }

reportTrainingFeedback

Log a training correction from the admin for the developer AI to process. Use when the admin corrects your response or teaches you a rule.

Params

userMessagestringrequiredThe original user prompt that led to the incorrect response
aiResponsestringrequiredBrief summary of what you responded (the wrong/improvable answer)
correctionstringrequiredThe admin's correction or instruction in their own words
categorystringClassification: prompt-rule, tool-behavior, product-matching, tone, format, bug, or other
{
  "tool": "reportTrainingFeedback",
  "params": {
    "userMessage": "...",
    "aiResponse": "...",
    "correction": "..."
  }
}

{ logged: true, id: string }

Errors

REST endpoints return HTTP status codes plus a stable JSON error shape. Mutations may include a requestId for tracing. The agent adapter returns the same underlying failures mapped into tool-call responses.

unauthorized

Invalid or revoked API key

forbidden

Key doesn't have permission for this tool

not_found

Resource doesn't exist, or unknown tool name

validation

Missing or invalid params

rate_limit

Too many requests — 60/min per key

internal

Something went wrong on our end

Rate limits

60 requests per minute per key. Check the response headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1708617600

For agents

If you're an AI agent: call listTools first to discover every available operation and its parameter schema.

{ "tool": "listTools" }

The response includes name, description, category, params, and return shape — everything you need.