Onboarding a New POS — Framework & Playbook¶
This is the step-by-step companion to ADR 0005. It defines what we ask the integrator, in what order we build, and when we're done when connecting a new POS to Cata's Standard API.
It is written to be driven by an AI agent in a conversation: the agent asks the questions below, you paste an API-docs URL and sample payloads, and the agent produces the adapter scripts. Nothing here requires a Go code change — see ADR 0001.
The five required topics¶
Every integration must implement these, in this dependency order:
| Order | Topic | Direction | Output contract |
|---|---|---|---|
| 1 | test_connection |
Cata → POS | contract |
| 2 | list_remote_outlets |
Cata → POS | contract |
| 3 | sync_products |
POS → Cata | contract |
| 4 | order_dispatch |
Cata → POS | contract |
| 5 | order_status_update |
POS → Cata | contract |
Optional, provider-dependent: sync_outlet, snooze_items. Add them only if
the POS and the business case need them.
The gate. We do not generate a topic's script until we have (a) the endpoint(s) it calls and (b) a real sample payload for it. Sample payloads win over vendor prose when they disagree.
Part A — Intake questionnaire (what the agent asks)¶
Answer as much as you can up front; the agent will ask follow-ups via the
generation pipeline's needs_clarification step
(central.adapter_generation_jobs) when it hits a gap.
A1. Provider basics¶
- Provider display name and proposed
slug(lowercase, e.g.iseller). - Vendor API documentation URL(s). Is it public, or behind partner/login auth?
- Do we have sandbox/test credentials? A production account?
- Is there a GitHub repo (ours or theirs) of API docs/samples we should register
as a
knowledge_basesentry?
A2. Authentication¶
- Auth model:
api_key·oauth·webhook_only· other? - Exact header(s) / format. (e.g. Revel:
API-AUTHENTICATION: {key}:{secret}.) - For OAuth: token + refresh flow, scopes, token lifetime, where the refresh token lives.
- Where do credentials live?
- Tenant-wide creds (key/secret/base URL) →
provider_connections(apiKey,apiSecret,baseUrl,config). - Per-outlet config (location id, dining-option ids, etc.) →
outlet_providers.settings. - Remember: secrets are never exposed to the JS sandbox; HMAC/credential material is resolved in Go (ADR 0003).
A3. Connectivity¶
- Base URL — global, or per-tenant (e.g.
https://{account}.vendor.com)? - Environments (sandbox vs prod base URLs).
- Rate limits (requests/min, burst, 429 behaviour).
- Pagination style — offset/limit, cursor,
meta.next, DRFnext? (The runtime'scontext.http.getAllhandles Revel-stylemeta.nextand DRF-stylebody.next; anything else needs a manual loop.) - Error envelope — does the API return non-2xx on error, or HTTP 200 with an
error body (e.g.
{"status":"ERROR", ...})? Give an example.
A4. Data formats¶
- Price units — integer cents or decimal? (Cata uses decimal; the script converts.)
- ID types — integers (need
String(id)) or already strings? - Timestamps — UTC or local? Format? Timezone source?
- Currency — fixed per outlet, or on the payload?
A5. Per-topic — endpoints + a sample for each¶
For each required topic, provide the endpoint(s) and a representative sample payload (real response/request, redacted as needed):
test_connection— the cheapest read-only call that proves the credentials work (e.g. "list locations", "get account"). Sample 200 body.list_remote_outlets— the locations/outlets endpoint. Sample response. What field is the stable location id?sync_products— catalog endpoint(s): products, modifier groups, modifier options. Sample payloads. How are bundles/combos modelled? What is the SKU/ item-code field? (Cata product sync is flat — no menu tree/categories.)order_dispatch— the create-order endpoint, full request schema, a sample request and a sample success response, plus a sample error. Whichoutlet_providers.settingsfields does it need (location id, payment type, dining options, …)? How is the external order id returned so we can reconcile?order_status_update— the webhook surface: which events fire, the signature scheme (e.g. HMAC-SHA256 over the raw body + which header), and a sample webhook body per event. Map each POS status to a Cata status (ACCEPTED/IN PROGRESS/READY/DRIVER PICKED UP/COMPLETED/CANCELLED). Are there non-Cata events we must skip (e.g. in-store orders)?
A6. Optional topics & reconciliation¶
sync_outlet— needed? endpoint + sample.snooze_items— does the POS support disabling products/modifier options? Endpoint(s)?- Idempotency — does replaying a create-order dedupe, or must we track the external id ourselves?
Part B — Step-by-step build¶
Step 0 — Scope¶
Confirm which of the five required topics apply (all, normally) and whether any optional topic is in scope. Record it at the top of the provider's knowledge pack.
Step 1 — Run intake¶
Work through Part A. Stop and collect missing samples before proceeding — the
gate applies per topic, not per provider, so you can start test_connection
while still gathering the order_dispatch sample.
Step 2 — Register provider + draft the knowledge pack¶
- Add a
central.providersrow (slug,display_name,auth_type,status) — seeded via the dashboard-app, not hand-edited in prod. - Register a
central.knowledge_basesrow if there's a docs repo. - Create
docs/guides/adapters/<slug>.mdfrom the knowledge-pack template and fill in everything you learned in intake.
Step 3 — Generate scripts, in dependency order¶
Generate test_connection → list_remote_outlets → sync_products →
order_dispatch → order_status_update. For each:
- Run it through the generation pipeline
(
AdapterGenerateService→central.adapter_generation_jobs). The job moves throughgathering → generating → testing; if it lacks a fact it parks atneeds_clarificationwith a question — answer it (human_response) rather than letting it guess. - The result is a
candidateincentral.adapter_scripts; runtime source is committed toscripts/adapters/<slug>/<topic>.jswith the standard JSDoc header (@provider,@topic,@version). - Every script reads only the fields it needs and matches the topic's
input/output shape in
adapter-script-contracts.md.
Step 4 — Test each candidate¶
- Validate output shape against the contract using the topic's sample payload.
- For read topics, deploy and exercise via API (see
adapter-scripts-dev-guide.md):POST /api/v1/provider-connections/<slug>/test,GET …/remote-outlets,POST /api/v1/products/sync. - Test against the real POS using a sandbox tenant's
provider_connections. - Respect the budgets (30s
order_dispatch, 10minsync_products); usegetAll/getBatch, not naive sequential loops.
Step 5 — Review & activate¶
A human reviews the candidate and promotes candidate → active (which deprecates
the prior active). This review is mandatory — see
ADR 0005.
Step 6 — Document & wire up¶
- Backfill the knowledge pack: final field maps, quirks, sample request/response.
- Add a
changelogentry in the pack. - Update the feature-parity note (which topics/features the provider supports vs N/A).
- Add the provider to
mkdocs.ymlnav under POS Adapter Scripts → Providers.
Part C — Definition of Done¶
A new POS is "onboarded" when:
- [ ]
central.providersrow exists; knowledge base registered (if any). - [ ]
docs/guides/adapters/<slug>.mdis complete (no[TBC]left for in-scope topics). - [ ] All five required scripts are
activeincentral.adapter_scriptsand committed underscripts/adapters/<slug>/. - [ ] Each script validated against a real sample payload and the topic contract.
- [ ]
order_dispatchverified end-to-end against the sandbox POS; the external order id is captured for reconciliation. - [ ]
order_status_updatemaps every relevant POS status to a Cata status and skips non-Cata events. - [ ] Feature-parity + changelog updated; provider added to mkdocs nav.
- [ ] Human review recorded (
reviewed_by) on every activated script.
Part D — Knowledge-pack template¶
Every docs/guides/adapters/<slug>.md uses these headings (this is the curated,
reviewed reference; adapters/revel.md is the worked
example). Per-topic output shapes are not restated here — link to
adapter-script-contracts.md.
# <Provider> — Adapter Guide
## Provider Info (slug, auth type, base URL, API docs link, scope of topics)
## Authentication (header format, input fields used, where creds live)
## API Endpoints (table: endpoint | method | used for | pagination)
## Pagination (style + helper pattern)
## Rate Limits (limits + 429 behaviour)
## Quirks & Constraints (price units, ID types, timestamps, bundles, fees, …)
## Feature Parity (which topics/features supported vs N/A)
## Topic: test_connection (API call, script, sample 200 body)
## Topic: list_remote_outlets (API call, script, expected output)
## Topic: sync_products (API calls, field mapping, sample in/out, bundles)
## Topic: order_dispatch (endpoint, required settings, body shape, field map,
response/error handling)
## Topic: order_status_update (webhook surface, signature, status mapping, skip rules)
## Topic: sync_outlet (optional)
## Topic: snooze_items (optional)
## Changelog (newest-first: version, what changed, what was tested)
## Open uncertainties (things still to confirm against the sandbox)
Related¶
- ADR 0005 — onboarding framework
- ADR 0004 — where provider docs live
- Adapter Script Contracts · Transformation Guidelines · Developer Guide
- First pack built with this framework: iSeller