Store onboarding
Onboarding turns a merchant into an integrated store: the merchant consents, your app gets a token for their organization, and each store you link starts sending orders to your webhook.
The flow
Section titled “The flow”-
Create a signup URL
Section titled “Create a signup URL”Your backend calls
POST /pos/signup_urlwith your client credentials over HTTP Basic and the merchant’s details. Quiqqy provisions the merchant account and store if they do not exist and returns a consent URL.Terminal window curl -s https://auth.quiqqy.ai/api/v2/pos/signup_url \-u "$QUIQQY_CLIENT_ID:$QUIQQY_CLIENT_SECRET" \-H 'Content-Type: application/json' \-d '{"location_id": "LOC-001","store_name": "Main Street Pizza","email": "owner@mainstreetpizza.example","first_name": "Jane","last_name": "Doe","business_phone": "+14155550134","address": {"street_address": "123 Main St","city": "New York","state": "NY","country": "US","zip": "10001"},"redirect_uri": "https://pos.example.com/quiqqy/callback","state": "af0ifjsldkj"}'const basic = Buffer.from(`${process.env.QUIQQY_CLIENT_ID}:${process.env.QUIQQY_CLIENT_SECRET}`,).toString('base64');const response = await fetch('https://auth.quiqqy.ai/api/v2/pos/signup_url', {method: 'POST',headers: { Authorization: `Basic ${basic}`, 'Content-Type': 'application/json' },body: JSON.stringify({location_id: 'LOC-001',store_name: 'Main Street Pizza',email: 'owner@mainstreetpizza.example',redirect_uri: 'https://pos.example.com/quiqqy/callback',state: crypto.randomUUID(),}),});const { signup_url } = await response.json();import osimport requestsresponse = requests.post("https://auth.quiqqy.ai/api/v2/pos/signup_url",auth=(os.environ["QUIQQY_CLIENT_ID"], os.environ["QUIQQY_CLIENT_SECRET"]),json={"location_id": "LOC-001","store_name": "Main Street Pizza","email": "owner@mainstreetpizza.example","redirect_uri": "https://pos.example.com/quiqqy/callback","state": "af0ifjsldkj",},)signup_url = response.json()["signup_url"]Useful request fields beyond the identity block:
redirect_uri(must match an Allowed Redirect URI on your credential),state(opaque CSRF value echoed back to you),flow_type(loginorsignup, to force one prompt), andlocale. -
Merchant consent
Section titled “Merchant consent”Redirect the merchant to
signup_url. They sign in or complete signup, review what your app is asking for, and approve. Quiqqy redirects to yourredirect_uriwith?code=…&state=…. Verifystate, then exchange the code for tokens as described in Authentication. From here on you hold a merchant Bearer token. -
List the merchant’s stores
Section titled “List the merchant’s stores”Terminal window curl -s https://auth.quiqqy.ai/api/v2/pos/stores \-H "Authorization: Bearer $ACCESS_TOKEN"200 OK [{"store_id": "st_8fk2c1p9","name": "Main Street Pizza","status": "active","integration_status": "not_integrated","integration": null}]integration_statusis one ofnot_integrated,pending,integrated,disabled. -
Integrate each store
Section titled “Integrate each store”Linking your app to a store is what turns on order delivery and menu sync for it:
Terminal window curl -s https://auth.quiqqy.ai/api/v2/pos/integrate-store/st_8fk2c1p9 \-H "Authorization: Bearer $ACCESS_TOKEN" \-H 'Content-Type: application/json' \-d '{"webhook_url": "https://pos.example.com/webhooks/quiqqy","notification_email": "ops@pos.example.com","menu_sync_direction": "pos_to_quiqqy","external_store_id": "LOC-001","auto_accept_orders": false}'const response = await fetch('https://auth.quiqqy.ai/api/v2/pos/integrate-store/st_8fk2c1p9',{method: 'POST',headers: {Authorization: `Bearer ${accessToken}`,'Content-Type': 'application/json',},body: JSON.stringify({webhook_url: 'https://pos.example.com/webhooks/quiqqy',menu_sync_direction: 'pos_to_quiqqy',external_store_id: 'LOC-001',auto_accept_orders: false,}),},);const integration = await response.json();await vault.store('quiqqy_webhook_secret', integration.webhook_secret);import requestsresponse = requests.post("https://auth.quiqqy.ai/api/v2/pos/integrate-store/st_8fk2c1p9",headers={"Authorization": f"Bearer {access_token}"},json={"webhook_url": "https://pos.example.com/webhooks/quiqqy","menu_sync_direction": "pos_to_quiqqy","external_store_id": "LOC-001","auto_accept_orders": False,},)integration = response.json()vault.store("quiqqy_webhook_secret", integration["webhook_secret"])200 OK {"integration_id": "int_3a2c8d1e","app_id": "app_7pk2mv9qx4rt","store_id": "st_8fk2c1p9","webhook_url": "https://pos.example.com/webhooks/quiqqy","webhook_secret": "b8f3a91c6e2d…64-hex-chars…4f7a","menu_sync_direction": "pos_to_quiqqy","auto_accept_orders": false,"external_store_id": "LOC-001","status": "active","connected_at": "2026-07-30T12:00:00.000Z"} -
Push the menu
Section titled “Push the menu”With the integration active, push the store’s catalogue — Menu sync. The store cannot sell what Quiqqy has never seen.
Request fields worth knowing
Section titled “Request fields worth knowing”| Field | On | Notes |
|---|---|---|
location_id | signup_url | Your identifier for the location; becomes the default external_store_id |
external_store_id | integrate-store | Echoed as X-Quiqqy-Location-Id on every webhook and as location_id in event envelopes — the key you route deliveries on |
menu_sync_direction | integrate-store | none, quiqqy_to_pos, pos_to_quiqqy, bidirectional. Menu pushes are rejected with menu.push_not_allowed unless the direction permits them |
auto_accept_orders | integrate-store | When true, Quiqqy confirms orders on your behalf the moment they are created; you still receive order.created and drive the rest of the lifecycle |
webhook_url | integrate-store | Per-store. Point every store at one endpoint and route on X-Quiqqy-Location-Id, or use distinct URLs — both are fine |
Managing the integration
Section titled “Managing the integration”| Call | Purpose |
|---|---|
GET /pos/integrations/:storeId | Current configuration and status |
PUT /pos/integrations/:storeId | Change webhook_url, menu_sync_direction, auto_accept_orders, rotate the webhook secret |
DELETE /pos/integrations/:storeId | Disconnect the store — order delivery and menu sync stop |
PUT /pos/stores/:storeId/settings | Store settings (hours, contact details) |
PUT /pos/stores/:storeId/status | Open, pause or close the store — see Item availability |
Integration lifecycle
Section titled “Integration lifecycle”not_integrated → pending → integrated, with disabled reachable from
integrated when the merchant uninstalls your app, you delete the
integration, or Quiqqy suspends it. A disabled integration receives no
webhooks and rejects POS calls for that store with store.not_integrated;
handle it by prompting the merchant to reconnect, not by retrying. Full
endpoint details are in the
Online Ordering reference.