Commerce
Commerce capabilities for Queek apps: orders, inventory, customers, discounts and coupons, loyalty and gift cards, payments, shipping and fulfilment, tax, subscriptions, B2B, markets and translations, data sync and sales channels.
Capabilities for orders, inventory, customers, discounts and coupons, loyalty and gift cards, payments, shipping and fulfilment, tax, subscriptions, B2B, markets and translations, data sync and sales channels. 29 capabilities on this page: 19 available, 2 partly available, 8 not yet available. 2 more are not offered by design.
Each entry says what the capability does, what is missing or worth knowing where that applies, a workaround where there is a gap, and how you reach it. An entry marked Not offered by design says why and what to use instead. Scope names are explained on Merchant API scopes; How to read this catalogue defines the labels.
Orders
Orders read, create, import and status
AvailableApps can list and read orders in the same shape the order webhooks send, create an order for a customer that waits for payment (priced by the same engine the dashboard uses), import orders already charged elsewhere idempotently, move orders through the status machine including payment approval and rider assignment, and patch shipment and extension fields. Imports take their source attribution from the authenticated app installation.
Good to know:
-
Imports accept only orders already charged outside Queek.
-
A created order is a real order that waits for payment by bank transfer or online; there is no separate draft record, no payment link in the response, and no way to create it already paid. Cash, wallet and split payments are not offered.
-
Created orders are for pickup, in-store or delivery with one price from the engine: an app cannot set a price, a total or a status, and creation takes no metafields (patch them afterwards).
-
Fulfilment orders are not available.
-
Only recorded payment and Queek wallet-refund transactions are readable.
-
Merchant-collected, offline, provider-side and manual-review refunds have no recorded refund row.
-
Payouts are read as settlement batches and as withdrawal and rider settlement rows through their own scopes (see Payout and settlement reads).
-
A generic app installation takes its source from its key and omits channel; a supplied channel is rejected with 422.
-
An installed legacy marketplace app must send a channel matching its own slug, or it receives 422.
-
An import made with a merchant’s own key must send a channel and may choose either legacy slug; the slugs are not reserved.
-
Order lines carry
variant_id(the variantp_id, null for a product without variants or a deleted variant),variant_uidand sku (the variant’s, or the product’s for a line without a variant), so sales per variant never need a match onvariant_title; the sku is the store’s current one, not a snapshot. -
The order list narrows to a creation window with
from_dateandto_date(whole days, YYYY-MM-DD) ordate_range(today,this_week,this_month), counted in the platform time zone (Africa/Lagos); they combine withupdated_afterand every other filter. -
An import’s
delivery_feeand discount are required (send 0.00 for none). On a dev store itsplaced_atbecomes the order’screated_at(updated_atstays the import time, soupdated_afterpolling still sees it) and must be within the last 120 days, the time a dev store keeps imported and generated test-data orders (older is 422; other dev-store orders are pruned at 30 days). On a live store the order is recorded now andplaced_atis kept as its order date. -
Routes:
GET api/v1/merchant/orders,POST api/v1/merchant/orders,GET api/v1/merchant/orders/{order},POST api/v1/merchant/orders/import,POST api/v1/merchant/orders/{order}/status -
Scopes:
merchant-orders-read,merchant-orders-create,merchant-orders-status-update
Returns and exchanges
Not yet availableApps can refund an order with line-level restocking through the refund operation, but there is no return workflow: no return request, no receive or inspect step and no exchange.
Workaround: Handle returns in the app-hosted flow, then refund the order with POST /orders/{order}/refunds; send the returned lines in line_items to put the stock back.
Inventory
Inventory, purchase orders and stock alerts
AvailableApps can read store-level on-hand stock, make audited set or delta adjustments, list suppliers, create and read purchase orders, receive goods against them (which adds stock), and list low-stock and out-of-stock products through the Merchant API. There are no locations or per-location levels, and a received purchase order line can name the variant it is for.
Good to know:
- No per-location stock.
- A level adjustment changes one item per call; only bulk restock handles several products, and it skips products with variants.
- Receiving a purchase order adds each line’s quantity to one variant (items[].variant, its
p_id) or, for a product without active variants, to the product’s stock. A line for a product with active variants must name a variant: the answer is 422variant_requiredand nothing is received. A line is a product-level allocation, so one line’s quantity cannot be split across several variants in a single request: send one receive per variant. - Receiving needs an Idempotency-Key header. It records the ordered unit cost on the receipt but never changes the product’s own cost price.
- Suppliers are read only: apps cannot create, change or delete them. Suppliers and purchase orders have no short numeric id, only an opaque one.
- A purchase order cannot be edited, cancelled or deleted through the API; the only change is receiving goods.
- Suppliers and purchase orders need the supplier management and purchase orders features on the store’s plan; a live store without them is refused with the usual upgrade-required answer. A dev store carries every plan feature, so build and test against them there; a live store needs the plan.
- There are no forecasts or reorder points.
- Adjustments do not check open-order reservations.
Workaround: Use a small limit when listing products with many variants: each product lists all of its variants, with no per-product cap. Create and edit suppliers, and cancel a purchase order, in the merchant dashboard.
- Routes:
POST api/v1/merchant/inventory/adjustments,GET api/v1/merchant/inventory/levels,POST api/v1/merchant/inventory/levels/adjustments,GET api/v1/merchant/inventory/low-stock,GET api/v1/merchant/inventory/out-of-stock,GET api/v1/merchant/suppliers,GET api/v1/merchant/purchase-orders,GET api/v1/merchant/purchase-orders/{po},POST api/v1/merchant/purchase-orders,POST api/v1/merchant/purchase-orders/{po}/receive - Scopes:
merchant-inventory-read,merchant-suppliers-read,merchant-purchase_orders-read,merchant-purchase_orders-detail,merchant-purchase_orders-create,merchant-purchase_orders-update
Customers
Customers and followers
AvailableList customers and followers with cursor pagination, each carrying its tags and filterable with the tag parameter; campaign audience reads can include non-buyers. Contact fields and email/SMS marketing consent state require the review-protected contact scope.
Good to know:
-
Use audience=campaign to include non-buyers; this mode requires
merchant-customers-contact-read. Poll this audience to discover new subscribers.not_opted_outmeans only that the person has not used Queek’s email unsubscribe; it is not permission to send. An import that storesinfo.marketing_opt_in=falseexcludes that contact from campaign reachability.sms_marketing_consent.stateisnot_subscribeduntil an app reports explicit opt-in; stored unsubscribed state and its consent timestamp remain visible even when the phone is absent or invalid;not_subscribedexposes no hidden ordering timestamp; phone presence and email consent do not imply SMS consent. -
Routes:
GET api/v1/merchant/customers -
Scopes:
merchant-customers-read,merchant-customers-contact-read
Segments, tags and consent
AvailableApps can read the campaign audience and email and SMS consent state, update consent for both channels, receive minimal consent events and manage saved customer segments: list, read, create, update and delete them, and preview who a set of rules matches. A previewed customer’s name, email and phone are null without merchant-customers-contact-read. Customers carry the store’s own tags, read on the customer object and matched by a segment rule (tags_any, any of the listed tags); a static segment stays the hand-picked grouping.
Good to know:
- Customer tags are the store’s own labels: a customer holds at most 250 tags of 255 characters, lowercased and deduplicated, and a tag name is private to its store. Apps read tags on the customer (tags) and in the customers/create and customers/update webhooks with the existing customers read grants, and a segment rule
tags_anymatches a customer carrying any of the listed tags. Apps cannot set a customer’s tags: the merchant sets them in the dashboard or the customer import. - App-reported consent evidence is not independently verified.
- An import that stores
info.marketing_opt_in=falseexcludes that contact from campaign reachability. - SMS consent is stored only from explicit app or provider reports; there is no WhatsApp consent state.
- A segment is a saved set of rules (
auto) or a hand-picked list of up to 1,000 customers (static). The built-in default segments are not listed; reproduce one with rules. - Segments are identified by a UUID and members by customer id. A segment’s stored recipient count is the count at its last save; the preview answers the live count.
- The
customer_idsof a static segment are store customer ids (thep_idfrom the customer reads), and an update that sendscustomer_idsreplaces the whole member list rather than adding to it. - Changing or deleting a segment a campaign uses changes who that campaign reaches at its next send. Apps cannot create or send campaigns.
- The segment scopes are customer-data scopes: declaring them needs approval, and installed stores must grant them.
Workaround: Create a static segment with the matching customer ids and send the complete member list on every update. Keep any attribute that is not a customer id in the app database and write its matches into the segment.
- Routes:
GET api/v1/merchant/customers,POST api/v1/merchant/customers/{customer}/email-marketing-consent,POST api/v1/merchant/customers/{customer}/sms-marketing-consent,GET api/v1/merchant/customer-segments,GET api/v1/merchant/customer-segments/{segment},POST api/v1/merchant/customer-segments,PATCH api/v1/merchant/customer-segments/{segment},DELETE api/v1/merchant/customer-segments/{segment},POST api/v1/merchant/customer-segments/preview - Scopes:
merchant-customers-read,merchant-customers-contact-read,merchant-customers-consent-update,merchant-customers-sms-consent-update,merchant-customer-segments-read,merchant-customer-segments-create,merchant-customer-segments-update,merchant-customer-segments-delete - Webhooks:
customers/update,customers_email_marketing_consent/update,customers_marketing_consent/update
Customer wishlists
AvailableShoppers can add, list and remove saved product and variant entries in a store-scoped wishlist through the storefront API, and apps with merchant-customers-detail can read a customer’s list. Only shoppers write, and Queek ships no wishlist page: an app supplies its own shopper interface.
Good to know:
- One flat list per store customer; no sharing or cross-store lookup.
- A wishlist holds at most 100 visible items.
- There are no wishlist events or webhooks: read a customer’s list again to see changes.
- Merchants and apps can only read; only signed-in shoppers write, through the storefront API.
- There is no Merchant API or app-proxy write: a wishlist change has to come from the shopper’s own signed-in session.
- Queek’s hosted storefront has no wishlist page, so the shopper-facing view is the app’s to build.
Workaround: Build the shopper interface in your own storefront code and call the storefront wishlist endpoints with the signed-in shopper’s token. Read any customer’s list from the Merchant API with the customer detail scope.
- Routes:
GET api/v1/client/store/wishlist-items,POST api/v1/client/store/wishlist-items,DELETE api/v1/client/store/wishlist-items/{ref},GET api/v1/merchant/customers/{customer}/wishlist-items - Scopes:
merchant-customers-detail
Discounts and coupons
Transform cart lines and bundles
Partly availableApps create scoped discounts with quantity and spend thresholds, priority and stacking, and manage priced add-on groups. All of it runs through the one price path the shopper sees, so the displayed price is the charged price. Apps cannot run code at cart time.
What’s missing:
- No code runs at cart time: an app cannot rewrite cart lines or reprice them.
- There is no rule for all of product A and B and no automatically added free gift; a fixed-price bundle is a product with its own price and stock.
- A discount is edited in place with PATCH api/v1/merchant/discounts/{discount} (scope
merchant-discounts-update): the usage count is kept and the shopper price follows the edit at once. The scope can reprice any live discount of the store, including ones the merchant made by hand, so the merchant approves it at install.
Workaround: Use quantity-threshold discounts for tiers, priced add-on groups for options, and a product with its own price for a fixed bundle.
- Routes:
POST api/v1/merchant/discounts,PATCH api/v1/merchant/discounts/{discount},POST api/v1/merchant/addon-groups - Scopes:
merchant-discounts-create,merchant-discounts-update
App checkout validation rules
Not yet availableNo app extension point validates a cart or order on the server beyond the platform’s own request checks.
Workaround: Enforce merchant-side rules through discount targeting and coupon limits when you create them.
Discounts and coupons create/publish
AvailableList, retrieve, create, edit, publish and unpublish discounts; list, create and edit coupons, all through the merchant API.
Good to know:
-
No cart/checkout-time custom logic: created discounts apply through the platform pricing path only.
-
Routes:
PATCH api/v1/merchant/discounts/{discount},PATCH api/v1/merchant/coupons/{coupon} -
Scopes:
merchant-discounts-create,merchant-coupons-create,merchant-discounts-update,merchant-coupons-update
Shopper coupon redemption on the storefront
AvailableThe storefront API can apply and remove a discount code on a shopper’s cart, checked against the same rules as checkout, and the cart totals show its effect. A code is consumed only when the order is placed, and no event tells an app that a code was redeemed.
Good to know:
- Apply requests are throttled to 10 per minute.
- Applying a code does not consume it: usage is counted when the order is placed.
- There is no separate redemption topic: an app learns which code was used from the
coupon_codeon the paid order, which the order webhook carries too.
Workaround: Read the paid order after checkout: its coupon_code names the discount code the shopper used (null when none) and its discount_total shows the effect. Webhooks carry the same object.
- Routes:
POST store/cart/discounts,DELETE store/cart/discounts/{code}
Loyalty and gift cards
Gift cards and store credit
Partly availableApps can sell a gift card as a digital product and issue each one as a single-use fixed-amount code that redeems at checkout. There is no balance ledger or store credit, so a partly used code is re-valued in place by lowering its value to the remainder.
What’s missing:
- A code redeems once for a fixed amount; there is no balance ledger and no store credit, so a partly used code burns its remainder.
- The wallet that holds marketplace refunds is not available to apps.
- A coupon is edited in place with PATCH api/v1/merchant/coupons/{coupon} (scope
merchant-coupons-update): lowerdiscount_valueto the remainder, and raiseusage_limit(never below the used count) andusage_limit_per_user(at most 10) to re-use a partly spent code. The code and the used count never change, so a card allows at most 10 redemptions per customer.
Workaround: Sell the card as a product, issue a fixed-amount code on orders/paid, and when a code is partly used lower its value to the remainder and raise its usage limit. Keep any balance record in the app’s own database.
- Routes:
POST api/v1/merchant/coupons,GET api/v1/merchant/coupons,PATCH api/v1/merchant/coupons/{coupon} - Scopes:
merchant-coupons-create,merchant-coupons-update - Webhooks:
orders/paid
Loyalty points ledger
Not offered by designApps keep their own points ledger and reward customers with discount codes created through the Merchant API.
No points ledger, earn or burn events, or checkout redemption API exists. An app can keep points itself but cannot apply them to the platform price.
Workaround: Credit points off paid-order webhooks in the app database and reward with coupons; reconcile reversals off cancelled-order events.
- Webhooks:
orders/paid
Payments
Refund an order
AvailableMerchants and apps with the merchant-orders-refund-create scope can refund an order payment, in full or in part, from the dashboard or with POST /orders/{order}/refunds. The refund follows the original payment: a payment the merchant took on their own gateway or offline is recorded only, with no money moved by Queek; a wallet payment goes back to the wallet; a card or bank payment Queek collected goes back to the original card or bank through the payment provider. The store’s ledger is debited, tracked stock is restocked and the customer is notified. Capture and void are not offered.
Good to know:
-
A refund cannot exceed what was received minus what was already refunded, and it cannot be undone.
-
A recorded refund moves no money: the merchant refunds the customer outside Queek.
-
A provider refund starts pending and ends success or failed: read it from the order’s refunds list or from the refunds/create and orders/updated events. A card refund can take up to 10 business days to reach the customer.
-
Idempotency-Key is required on every refund request.
-
Provider refunds are available for Naira payments Queek collected through Paystack, within the provider’s one-year window; other payments are refunded to the wallet or recorded.
-
Capture and void are not offered by design: Queek charges the customer immediately, so there is no authorised-but-uncaptured payment to capture or void.
-
The scope is review-required: an app holds it only with the merchant’s approval.
-
Routes:
POST api/v1/merchant/orders/{order}/refunds -
Scopes:
merchant-orders-refund-create -
Webhooks:
refunds/create,orders/updated
Payout and settlement reads
AvailableApps can read what the store has been paid and what has left it. Released daily seller settlement batches and their order entries need merchant-payout-batches-read; bank withdrawals and rider settlements need merchant-payout-ledger-read, a separate grant that shows the destination bank by name and last four digits only.
Good to know:
-
Payouts are read only: an app cannot start a withdrawal, change a bank account or move money.
-
A withdrawal shows the bank name and the last four digits of the account. The account holder, the full number and the bank code are never returned.
-
A batch is one released day of order settlements. Withdrawals and rider settlements are separate rows, read with payout-transactions and their own scope.
-
Withdrawals and rider settlements are identified by a UUID, not a short numeric id.
-
Both scopes are available to installed apps only, with merchant approval.
-
Routes:
GET api/v1/merchant/payouts,GET api/v1/merchant/payouts/{payout},GET api/v1/merchant/payout-transactions,GET api/v1/merchant/payout-transactions/{transaction} -
Scopes:
merchant-payout-batches-read,merchant-payout-ledger-read
Register an app payment provider
AvailableReleased first-party payment apps add a payment provider through their manifest. The merchant installs the app, then connects and verifies credentials per store in the dashboard.
Good to know:
- Approved Queek-built payment apps register providers. Third-party apps cannot: keeping third-party code out of the charge path is deliberate.
- A registered provider is not available until the merchant has an active install of the app and verified gateway credentials.
Workaround: A merchant who needs a provider Queek does not yet carry can connect one of the supported providers in the dashboard.
- Manifest:
payment_provider - Configuration:
payment_providers
Refund and payment events
AvailableApps can subscribe to refunds/create, sent whenever Queek records a refund: a refund to the customer’s wallet, a refund to the original card or bank through the payment provider, or a refund the merchant recorded after refunding outside Queek. Apps with the merchant-orders-read grant receive it. A card or bank refund finishing or failing is signalled by orders/updated and shown in the order’s refunds list. There is no other payment-specific topic.
Good to know:
-
refunds/create is sent once, when the refund is created, with its state at that moment; a card or bank refund is usually pending then, and it finishing or failing is signalled by orders/updated and shown in the order’s refunds list.
-
The payload is small: the refund id, the order id, the refunded payment id, the amount as a decimal string with its currency, the status, the type (
wallet_credit,original_paymentor recorded), the reason (order_cancelledormerchant_refund), and the time. It carries no note, customer details or balances. -
Delivery needs an active installation that holds
merchant-orders-read, the scope that also gates recorded payments and refunds on the order read. -
Delivery is at least once; an app added later is not sent refunds already made and reads them from the order.
-
There are no payment-created, payment-failed or payout topics.
-
Scopes:
merchant-orders-read -
Webhooks:
refunds/create,orders/updated
Create and resolve payment sessions
Not yet availableApp credentials expose no payment-session endpoint. Queek checkout runs the merchant or platform provider flow, so an app cannot create, resolve or reject a payment session.
Good to know:
- Apps cannot start Queek checkout payments or receive payment-session callbacks through app credentials.
Workaround: An installed app can import orders already charged on its external platform with POST /orders/import. This records the payment but does not create or resolve a payment session.
Shipping and fulfilment
Live carrier rates at checkout
Not yet availableA shipping app cannot return live rates into checkout. Apps can manage static shipping zones, but checkout has no carrier callback for live quotes.
Workaround: Keep merchant-configured flat zones, or quote live rates on the app-hosted page before handing the shopper to checkout.
- Scopes:
merchant-shipping-read
Fulfil shipped orders
AvailableApps can fulfil shipped orders end to end: react to orders/paid, write the carrier and tracking, assign the store rider and move the order status. Each store is one fulfilment location, and orders have no accept or reject step for external providers.
Good to know:
- Each store is one fulfilment location: there are no fulfilment locations and no per-location stock.
- There is no fulfilment-order workflow and no accept or reject step for external providers.
- The shipment write needs a shipping-method or courier order: self-delivery and pickup orders answer 404, so read the order’s delivery method first.
Workaround: Subscribe to orders/paid, write carrier and tracking through the shipment endpoint, then move the order status. For self-delivery and pickup orders assign the store rider and move the status instead.
- Routes:
POST api/v1/merchant/orders/{order}/assign-rider,PATCH api/v1/merchant/orders/{order}/shipment,POST api/v1/merchant/orders/{order}/status - Scopes:
merchant-orders-status-update - Webhooks:
orders/paid,orders/fulfilled
Shipment tracking writes
AvailableApps can write carrier, tracking number, tracking URL and shipment status onto an order through the merchant API.
Good to know:
-
Writes only; there is no carrier tracking-event callback or polling contract.
-
Routes:
PATCH api/v1/merchant/orders/{order}/shipment -
Scopes:
merchant-orders-update
Static shipping zones and rates
AvailableApps can list, create and update the merchant static shipping zones and rates through the merchant API.
Good to know:
-
Flat merchant-configured zones only; no live rate callback (see carrier rates).
-
Routes:
GET api/v1/merchant/shipping-zones -
Scopes:
merchant-shipping-read,merchant-shipping-create
Tailor checkout delivery options
Not offered by designQueek presents one resolved Delivery option per order; shape the offer with shipping zones and the store’s own delivery settings.
No app hook can rename, reorder, hide or generate delivery choices at checkout. The available delivery modes are merchant configuration.
Workaround: Shape the offer with the merchant-configured fulfilment modes for each store.
Tax
App-calculated tax at checkout
Not yet availableApps have no tax-calculation callback, and there is no tax-provider integration. Checkout applies only the tax rows the merchant configured.
Workaround: Ship jurisdiction logic in the app-hosted flow and keep the store rows aligned with it.
Tax rows through the app API
AvailableApps can list, read, create and change the store’s tax rows (name, rate, channel, priority, active) through the Merchant API, with the same rules as the dashboard. Checkout still applies only those rows.
Good to know:
- A store keeps one active tax per channel: switching a tax on, or moving an active tax into a channel, switches off that channel’s other active tax. A tax on
allapplies together with the active tax of the checkout’s own channel. - Taxes are exclusive: a rate is added on top of the discounted subtotal and never included in a price. Several taxes that apply are added side by side, never compounded, and each is rounded in the store’s currency.
- A rate is 0 to 100 percent with at most two decimals. It is not validated against any country’s tax rules: the merchant is responsible for the rate.
- There is no delete: switch a tax off with
active: false. A name is unique per channel, switched-off taxes included, so bring a tax back withactive: true. - There is no tax-calculation callback and no tax-provider integration.
- The write scopes change what shoppers are charged: declaring them needs app approval, and installed stores must grant them. Reading taxes does not need approval.
Workaround: For jurisdiction logic, keep it in the app-hosted flow and write the resulting rows here.
- Routes:
GET api/v1/merchant/taxes,GET api/v1/merchant/taxes/{tax},POST api/v1/merchant/taxes,PATCH api/v1/merchant/taxes/{tax} - Scopes:
merchant-taxes-read,merchant-taxes-create,merchant-taxes-update
Subscriptions
Recurring purchases
Not yet availableThe subscription feature bills merchants for their Queek plan, not shoppers. Apps get no customer subscription plans, billing contracts, renewal orders or billing attempts.
Workaround: Bill repeat purchases outside Queek and create each order through normal checkout when it is due.
B2B
Company catalogs and price lists
Not yet availableApps have no company, contact or location model, no negotiated catalogs or price lists, and no company payment terms. Price resolution stays on the single customer-price path.
Workaround: Keep the business-buyer mapping in the app database; it cannot change the platform price.
Markets and translations
Regional catalogs and display currency
Not yet availableApps have no market, catalog or currency-context API. Currency is store and provider configuration, with no market-specific publication.
Workaround: Run one store per currency region and convert for display on the app-hosted page.
Translated commerce content
AvailableApps can read and write locales, translatable content and translations through the Merchant API, set the store’s default language, and receive locale and translation webhooks. Translations are not scoped to markets.
Good to know:
- Translation writes carry at most 100 items per call.
- A stored translation keeps the digest of the source it was written against and reads back outdated once the source changes.
- A write must echo the current digest of each item, or the whole batch is rejected.
- The
theme_stringtype is one record per store, keyed <theme-slug>.<dotted-key>; its English defaults travel with the active theme. - The storefront serves
theme_stringoverrides for non-primary published locales. theme_stringkeys carry the theme slug, so switching theme leaves the old slug overrides dormant until pruned.machine_translation_allowedadvises against machine-filling privacy-policy, terms-of-service, returns-policy and shipping-policy.- Manual writes to those policy pages stay allowed.
- The default language (POST locales/{locale}/default) sets which published locale the root address serves; empty means the primary.
- Changing the default language emits locales/update for the gaining and the losing locale.
- Translations are per store and locale, not per market: apps have no market model, so one translation serves that locale everywhere the store sells.
Workaround: Read current digests from the translatable-resource show endpoint, echo them on write, and chunk larger jobs into batches of 100 items. Re-read after a theme publish. Policy pages accept manual writes.
- Scopes:
merchant-locales-read,merchant-locales-write,merchant-translations-read,merchant-translations-write - Webhooks:
locales/create,locales/update,locales/destroy,translations/update,translations/delete
Data sync
Bulk export and change feed
AvailableAn app can queue a whole-store export file (POST exports, then read the export until its download link is ready) and poll product, order and customer lists with best-effort updated_after reads. The export carries only the resources the app can read, with customer contact blank unless the app holds the contact scope. Deleted products and customers arrive as webhooks, so an app does not need to diff to find them.
Good to know:
- The export is a zip of products.csv, orders.csv and customers.csv with a manifest.json. Each file is included only when the app holds
merchant-items-read,merchant-orders-readormerchant-customers-read; an app holding none of them cannot export. Withoutmerchant-customers-contact-readthe name, email and phone cells are blank. - The export is built in the background and is a snapshot of the moment it was built. Order line items, delivery addresses and saved customer addresses are not in the files; manifest.json lists what is missing.
- One export runs per store at a time, and an installation may request three per 24 hours.
- The download link is a bearer link valid for seven days: anyone holding it can download the customer data in the archive. The two export scopes are protected, so adding them to an app version needs Queek review and the merchant approves them at install.
- Only product, order and customer lists support
updated_after. - Product changes to variants, images, metafields, stock, region, price, discounts, bulk publish, unpublish, archive status or inventory tracking may be missed.
- Order changes to items, properties, shipment, metafields or the customer profile may be missed.
- Customer changes are compared on each customer’s
updated_at, which has second precision; changes stored outside the customer record, such as order history, may be missed. - Deletions arrive as products/delete and customers/delete webhooks, which carry the product or only the customer id. A customer who stops being a customer without the row being removed is reported by customers/delete as well. The lists and the export do not mark a record as removed, and delivery is at least once.
- Long-running updates can appear late.
- The comparison time is not returned and may differ from each object’s
updated_at. - There is no snapshot or high-water mark for the lists.
Workaround: Request an export for the first full load, then poll products, orders and customers with updated_after, starting each poll at least five minutes before the previous poll started. Deduplicate by resource id, keep other filters fixed, consume webhooks including products/delete and customers/delete, and reconcile occasionally against a fresh export (or a full list walk) with what the app holds.
- Routes:
POST api/v1/merchant/exports,GET api/v1/merchant/exports/{export} - Scopes:
merchant-exports-create,merchant-exports-read,merchant-items-read,merchant-orders-read,merchant-customers-read - Webhooks:
products/delete,customers/delete
Idempotency, cursors and rate policy
AvailableApp writes are idempotent, list APIs page with cursors, and rate limits and retry guidance are published. There is no bulk reconciliation envelope.
Good to know:
- There is no bulk reconciliation endpoint; reconcile with cursor reads and
updated_after(see Bulk export and change feed).
Workaround: Send an idempotency key on every write, page with cursors, and wait for Retry-After on a 429.
Sales channels
Product feed and external order import
AvailableApps build product feeds and channel syncs from Merchant API reads: each product carries its storefront url, base price and storefront_price (the shopper price), currency, barcode, stock, images and variants; a registered publication limits the list to the products published to it; updated_after surfaces edited products and a full list walk reconciles stock, price and removals; an order imported with a publication carries its p_id. The app generates and uploads the feed itself; brand, condition and channel category are not product fields, so read them from merchant-defined metafields or map them in the app.
Good to know:
-
Pull only: nothing is pushed to the app.
updated_afterfinds new and edited product rows but can miss variant, image, metafield, stock, price and discount changes, so re-read the full list on a schedule for price and stock, and use that full walk to find removals. -
No per-product sync status or rejection reason can be written back to Queek; the app keeps its own feed status.
-
Each product and variant carries a base
priceand a shopperstorefront_price(usestorefront_pricein a feed), both in the product'scurrency; there are no per-market prices, so the app converts when a channel needs another currency. -
Product list rows include drafts and out-of-stock products; filter on status and published before emitting a feed.
-
No brand, condition or channel-category field on the product; use a merchant-defined, non-hidden metafield (the product object carries metafields) or app-side mapping.
-
Imported orders must already be charged externally.
-
Routes:
GET api/v1/merchant/publications,GET api/v1/merchant/products -
Scopes:
merchant-items-read,merchant-publications-read,merchant-orders-import
App capabilities
What a Queek app can do today, by area: the capabilities you can build with, how to reach each one, what is missing and the workarounds, plus example apps.
Storefront and content
Storefront and content capabilities for Queek apps: storefront, content, reviews, messaging and conversations.