Introduction

View as MarkdownOpen in Claude

Standardized API layer for Point-of-Sale (POS) integrations supporting multiple POS systems including Deliverect, Lightspeed, and Atlas Kitchen.

This service provides a unified abstraction layer that standardizes interactions with different POS systems using the adapter pattern.

Partner Integration (H2H)

External POS partners (e.g. Jamezz, Uber, QR vendors) integrate with pos-integration-service host-to-host. Operations tagged Partner H2H below are the supported partner surface.

Authentication

Every partner request carries a partner API key:

1X-Api-Key: <partner-api-key>

The key is tenant-scoped. Validation is silent on the key’s purpose — an invalid or expired key always returns 401 Unauthorized. Rotate keys by issuing a new one and revoking the old one in the admin console.

Coming soon — OAuth 2.0 with scoped permissions. A future release will offer OAuth 2.0 alongside the API-key flow, with per-operation scopes (e.g. products:read, orders:write, loyalty:*) for partners that need granular access control. API-key auth will remain supported as the simple path. No migration required for today’s partners.

Tenant resolution

The tenant is resolved from the request hostname. Each tenant has a subdomain, e.g.:

1https://{tenant}.sgp.samba-technologies.xyz/service/pos-integration/api/v1/...

Partners do not pass a tenant header themselves. Pointing the request at the right subdomain is what selects the tenant’s database and loyalty credentials.

Auth smoke test

Before integrating any business endpoint, verify the key works:

$curl -i "https://{tenant}.sgp.samba-technologies.xyz/service/pos-integration/api/v1/auth/whoami" \
> -H "X-Api-Key: <partner-api-key>"

200 with { "authenticated": true, "tenantId": "...", "apiKeyId": N, "expiresAt": "..." } confirms auth + subdomain routing are correct. 401 means the key is missing/invalid/expired.

Idempotency

Mutating operations accept a caller-supplied idempotency key where noted (commonly refCode). Replays with the same key return a success response without performing the action twice.

Error envelope

All error responses follow the same shape:

1{
2 "error": {
3 "code": 401,
4 "message": "invalid api key",
5 "details": "the provided X-Api-Key is invalid or expired"
6 }
7}

code mirrors the HTTP status. Partner-relevant categories:

HTTPMeaning
400Client-side: body/query validation failed. Fix and retry.
401API key missing, invalid, or expired. Do not retry; re-authenticate.
404Referenced resource (outlet, product, customer) not found.
409Conflict on a unique constraint (e.g. duplicate outlet external ID).
429Rate-limited (reserved — no limit enforced today).
500Server-side error. Safe to retry with backoff.
502Upstream dependency (e.g. loyalty-service) returned an error. Retry later.
503Tenant not fully configured (e.g. missing loyalty credential).
504Upstream timeout. Retry with backoff.

Loyalty proxy

The /api/v1/loyalty/* endpoints are thin proxies to a separate loyalty-service. The partner still uses their own X-Api-Key; pos-integration translates to the tenant’s loyalty credential internally. A 503 on these endpoints means the tenant hasn’t finished loyalty onboarding.

Date & Time Convention

All date-time fields in requests and responses use RFC 3339 format (a strict profile of ISO 8601):

  • DateTime: 2026-03-16T15:05:33Z or 2026-03-16T15:05:33+08:00
  • Date-only (where noted): 2026-03-16

JavaScript’s new Date().toISOString() produces valid values. The API accepts both Z (UTC) and ±HH:MM timezone offsets.

Menu V1Menu V2
ApproachPOS-driven menu syncCata-owned menu composition
How it worksPOS pushes a full menu tree (Menu → Categories → Items → Modifiers) to CataCata composes menus from flat products with sections, per-menu pricing, operating hours, and multi-store assignment
Data flowPOS → Cata (one-way push)Cata UI → Cata Backend (full CRUD)
Menu structureDefined by POS systemDefined by Cata user via Menu Manager
PricingInherited from POSPer-menu overrides (base_price, special_price)
SectionsAuto-created from POS categories (2-level tree)Custom sections with display types (LIST, GRID, HIGHLIGHT, SWIMLANE)
Multi-storeOne menu per store pushOne menu assigned to many stores
Publish flowImmediate on syncDraft → Publish workflow
StatusLegacy — will be deprecatedActive — recommended for new integrations

Data Flow Overview

1POS Adapter (X-Provider header)
2 ├── POST /api/v1/outlets/sync → stores, store_credentials
3 └── POST /api/v1/products/sync → items, item_modifiers, item_modifier_options
4
5Cata Menu Editor (no provider)
6 ├── Menu V2 Draft endpoints → menu_drafts, menu_draft_*
7 └── Publish → menus, menu_*, item_store

Contact Support: Name: CATA Projects Email: support+api@cata.sg