Xe POS API
Build customer-facing mobile apps, e-commerce storefronts, kiosk UIs, or back-office integrations on top of your POS data — all scoped to your store's isolated Firebase so no two subscribers ever share data.
Grocery / Retail app
Browse products, check stock, place pickup or delivery orders.
Restaurant ordering app
Menu display, table QR ordering, kitchen status updates in real-time.
E-commerce storefront
Full product catalog + cart + online checkout backed by your POS inventory.
Back-office dashboard
Sales reports, daily totals, inventory alerts for managers.
# Data architecture
api.xeboki.com/v1/pos/* ← REST (server-side, batch reads)
firestore.googleapis.com ← Real-time SDK (live order status, menu changes)
# Your store data lives in YOUR Firebase — isolated, never shared
Base URL
https://api.xeboki.com/v1/posAuthentication
The POS API has three authentication layers depending on what you're building. All requests go through api.xeboki.com — never directly to Firebase.
API Key
All requests. Your xbk_live_* key with pos:* scopes. Identifies your store.
Customer JWT
Customer-facing endpoints. Short-lived token from login/register. Scopes access to that customer's data only.
Firebase Custom Token
Real-time SDK. Returned alongside the customer JWT. Use with Firebase Auth to listen to live Firestore updates.
1. API Key — every request
Create a key at account.xeboki.com/connected-apps with pos:* scopes. Pass it in every request header.
Required header
| Parameter | Type | Description |
|---|---|---|
Authorizationrequired | string | Bearer xbk_live_your_key_here |
curl https://api.xeboki.com/v1/pos/products \
-H "Authorization: Bearer xbk_live_your_key_here"2. Customer JWT — customer-facing endpoints
Endpoints like order history, loyalty points, and profile require a customer JWT. Obtain it via login or register. Pass it alongside your API key.
// Add X-Customer-Token for customer-scoped endpoints
fetch('https://api.xeboki.com/v1/pos/customers/me', {
headers: {
'Authorization': 'Bearer xbk_live_...',
'X-Customer-Token': 'eyJhbGci...', // from login/register
}
})3. Firebase Custom Token — real-time data
The login/register response includes a firebase_token. Use it with the Firebase SDK to authenticate into your store's isolated Firestore and subscribe to live updates — order status changes, menu updates, stock levels — without polling.
import { initializeApp } from 'firebase/app';
import { getAuth, signInWithCustomToken } from 'firebase/auth';
import { getFirestore, doc, onSnapshot } from 'firebase/firestore';
// 1. Login via POS API → get firebase_token
const { customer, firebase_token, firebase_config } = await loginCustomer();
// 2. Init Firebase with YOUR store's config
const app = initializeApp(firebase_config);
const auth = getAuth(app);
await signInWithCustomToken(auth, firebase_token);
// 3. Subscribe to live order status
const db = getFirestore(app);
onSnapshot(doc(db, 'orders', orderId), (snap) => {
const order = snap.data();
console.log('Order status:', order.status); // 'preparing' | 'ready' | 'delivered'
});Products & Categories
Your full product catalog — prices, descriptions, images, modifiers, and category groupings. Scoped to your store only.
https://api.xeboki.com/v1/pos/productsList products
Returns all active products. Supports filtering and search.
Query parameters
| Parameter | Type | Description |
|---|---|---|
category_id | string | Filter by category ID. |
search | string | Full-text search on name and description. |
in_stock | boolean | true = only products with stock > 0. |
limit | integer | Max results. Default: 50, max: 200. |
offset | integer | Pagination offset. Default: 0. |
curl "https://api.xeboki.com/v1/pos/products?category_id=cat_abc&in_stock=true" \
-H "Authorization: Bearer xbk_live_..."Response 200
{
"products": [
{
"id": "prod_abc123",
"name": "Margherita Pizza",
"description": "Classic tomato and mozzarella",
"price_cents": 1299,
"currency": "usd",
"category_id": "cat_pizza",
"image_url": "https://...",
"in_stock": true,
"stock_qty": null,
"modifiers": [
{ "group": "Size", "options": ["Small","Medium","Large"], "required": true }
],
"tags": ["vegetarian"],
"is_active": true
}
],
"total": 42,
"offset": 0
}https://api.xeboki.com/v1/pos/products/{product_id}Get product
Full product detail including all modifier groups and options.
curl "https://api.xeboki.com/v1/pos/products/prod_abc123" \
-H "Authorization: Bearer xbk_live_..."https://api.xeboki.com/v1/pos/categoriesList categories
Returns all active categories ordered by sort order. Use to build your navigation sidebar or tab bar.
curl "https://api.xeboki.com/v1/pos/categories" \
-H "Authorization: Bearer xbk_live_..."Response 200
{
"categories": [
{ "id": "cat_pizza", "name": "Pizza", "icon": "pizza", "color": "#E74C3C", "sort_order": 0 },
{ "id": "cat_drinks", "name": "Drinks", "icon": "drink", "color": "#3498DB", "sort_order": 1 }
]
}https://api.xeboki.com/v1/pos/products/{product_id}/stockCheck stock
Real-time stock check for a specific product. For live updates across your whole menu, use the Firebase SDK instead — see Real-time.
curl "https://api.xeboki.com/v1/pos/products/prod_abc123/stock" \
-H "Authorization: Bearer xbk_live_..."Response 200
{ "in_stock": true, "qty": 24, "low_stock_threshold": 5, "low_stock": false }Customers
Customer accounts scoped to your store. Supports loyalty points, order history, and saved preferences. A customer in your store is completely independent of any other store's customers.
https://api.xeboki.com/v1/pos/customers/registerRegister customer
Create a new customer account. Returns a JWT + Firebase custom token immediately — sign them into Firebase for real-time order tracking right after registration.
Request body
| Parameter | Type | Description |
|---|---|---|
emailrequired | string | Customer email. Unique within your store. |
passwordrequired | string | Min 8 characters. |
full_name | string | Display name. |
phone | string | Phone number for order notifications. |
curl -X POST "https://api.xeboki.com/v1/pos/customers/register" \
-H "Authorization: Bearer xbk_live_..." \
-H "Content-Type: application/json" \
-d '{
"email": "jane@example.com",
"password": "s3cur3pass",
"full_name": "Jane Smith",
"phone": "+15551234567"
}'Response 201
{
"customer": {
"id": "cust_xyz", "email": "jane@example.com",
"full_name": "Jane Smith", "loyalty_points": 0
},
"token": "eyJhbGciOiJIUzI1NiJ9...",
"firebase_token": "eyJhbGciOiJSUzI1NiJ9...",
"firebase_config": {
"apiKey": "AIza...",
"authDomain": "your-store-12345.firebaseapp.com",
"projectId": "your-store-12345",
"storageBucket": "your-store-12345.appspot.com",
"messagingSenderId": "123456789"
}
}https://api.xeboki.com/v1/pos/customers/loginLogin customer
Authenticate an existing customer. Returns JWT + Firebase custom token.
Request body
| Parameter | Type | Description |
|---|---|---|
emailrequired | string | Customer email. |
passwordrequired | string | Customer password. |
curl -X POST "https://api.xeboki.com/v1/pos/customers/login" \
-H "Authorization: Bearer xbk_live_..." \
-H "Content-Type: application/json" \
-d '{"email":"jane@example.com","password":"s3cur3pass"}'https://api.xeboki.com/v1/pos/customers/meGet customer profile
Returns the authenticated customer's profile including loyalty points and address book.
curl "https://api.xeboki.com/v1/pos/customers/me" \
-H "Authorization: Bearer xbk_live_..." \
-H "X-Customer-Token: eyJhbGci..."Response 200
{
"customer": {
"id": "cust_xyz", "email": "jane@example.com",
"full_name": "Jane Smith", "phone": "+15551234567",
"loyalty_points": 250, "loyalty_tier": "Gold",
"addresses": [
{ "id": "addr_1", "label": "Home", "line1": "123 Main St", "city": "New York", "default": true }
]
}
}https://api.xeboki.com/v1/pos/customers/me/ordersOrder history
Returns the customer's order history, most recent first.
Query parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Max results. Default: 20. |
status | string | Filter: pending | preparing | ready | delivered | cancelled. |
curl "https://api.xeboki.com/v1/pos/customers/me/orders?limit=10" \
-H "Authorization: Bearer xbk_live_..." \
-H "X-Customer-Token: eyJhbGci..."Orders
Create and track orders. Supports dine-in, takeaway, delivery, and e-commerce order types. Once created, track order status in real-time via Firebase — see Real-time.
pending → confirmed → preparing → ready → delivered. Subscribe to orders/{orderId} in Firestore for real-time status updates.https://api.xeboki.com/v1/pos/ordersCreate order
Place a new order. The order is immediately visible in the POS terminal. Payment is handled separately — for online payment, use your Stripe integration after creating the order.
Request body
| Parameter | Type | Description |
|---|---|---|
order_typerequired | string | "dine_in" | "takeaway" | "delivery" | "ecommerce". |
itemsrequired | array | Array of line items — see schema below. |
customer_id | string | Attach order to a customer for loyalty + history. |
table_id | string | For dine_in orders. |
delivery_address | object | Required if order_type is "delivery". |
notes | string | Special instructions for the kitchen. |
coupon_code | string | Discount coupon code. |
curl -X POST "https://api.xeboki.com/v1/pos/orders" \
-H "Authorization: Bearer xbk_live_..." \
-H "Content-Type: application/json" \
-d '{
"order_type": "takeaway",
"customer_id": "cust_xyz",
"items": [
{
"product_id": "prod_abc123",
"qty": 2,
"modifiers": [{ "group": "Size", "option": "Large" }],
"notes": "extra cheese"
}
],
"notes": "No onions please"
}'Response 201
{
"order": {
"id": "ord_9f3k2",
"order_number": 1042,
"status": "pending",
"order_type": "takeaway",
"items": [
{ "product_id": "prod_abc123", "name": "Margherita Pizza", "qty": 2,
"unit_price_cents": 1299, "total_cents": 2598,
"modifiers": [{ "group": "Size", "option": "Large" }] }
],
"subtotal_cents": 2598,
"discount_cents": 0,
"tax_cents": 208,
"total_cents": 2806,
"currency": "usd",
"estimated_ready": "2026-03-31T12:25:00Z",
"created_at": "2026-03-31T12:15:00Z"
}
}https://api.xeboki.com/v1/pos/orders/{order_id}Get order
Fetch current order state. For live updates subscribe via Firebase instead.
curl "https://api.xeboki.com/v1/pos/orders/ord_9f3k2" \
-H "Authorization: Bearer xbk_live_..."https://api.xeboki.com/v1/pos/ordersList orders
Admin endpoint. List all orders with filtering. Requires pos:orders:read scope.
Query parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status. |
date_from | string | ISO date. e.g. 2026-03-01. |
date_to | string | ISO date. |
limit | integer | Default: 50, max: 200. |
offset | integer | Pagination. |
curl "https://api.xeboki.com/v1/pos/orders?status=pending&limit=20" \
-H "Authorization: Bearer xbk_live_..."Cart
Calculate order totals before creating an order — applies discounts, loyalty, taxes, and delivery fees server-side.
https://api.xeboki.com/v1/pos/cart/calculateCalculate cart totals
Stateless endpoint — does not save anything. Call it on every cart change to show live totals, applied discounts, and estimated taxes to the customer before they confirm.
Request body
| Parameter | Type | Description |
|---|---|---|
itemsrequired | array | Same format as order items. |
coupon_code | string | Discount code to validate and apply. |
customer_id | string | Apply loyalty discounts for this customer. |
delivery_fee_cents | integer | Delivery charge to include in total. |
curl -X POST "https://api.xeboki.com/v1/pos/cart/calculate" \
-H "Authorization: Bearer xbk_live_..." \
-H "Content-Type: application/json" \
-d '{
"items": [{ "product_id": "prod_abc123", "qty": 2, "modifiers": [{ "group": "Size", "option": "Large" }] }],
"coupon_code": "SUMMER20",
"customer_id": "cust_xyz"
}'Response 200
{
"items": [...],
"subtotal_cents": 2598,
"discount_cents": 520,
"discount_label": "SUMMER20 (20% off)",
"loyalty_discount": 0,
"tax_cents": 166,
"delivery_fee_cents": 299,
"total_cents": 2543,
"currency": "usd",
"coupon": { "code": "SUMMER20", "valid": true, "type": "percent", "value": 20 }
}Inventory
Stock levels for your products. For a live stock counter in your app, subscribe to the inventory Firestore collection via the Firebase SDK.
https://api.xeboki.com/v1/pos/inventoryList stock levels
Query parameters
| Parameter | Type | Description |
|---|---|---|
low_stock_only | boolean | true = only items below their low-stock threshold. |
out_of_stock | boolean | true = only items with qty ≤ 0. |
curl "https://api.xeboki.com/v1/pos/inventory?low_stock_only=true" \
-H "Authorization: Bearer xbk_live_..."Response 200
{
"inventory": [
{ "product_id": "prod_abc123", "product_name": "Margherita Pizza",
"qty": 3, "low_stock_threshold": 5, "low_stock": true, "unit": "pcs" }
]
}https://api.xeboki.com/v1/pos/inventory/{product_id}Get item stock
curl "https://api.xeboki.com/v1/pos/inventory/prod_abc123" \
-H "Authorization: Bearer xbk_live_..."Reports
Back-office analytics. Requires pos:reports:read scope. Never expose this to customer-facing apps.
https://api.xeboki.com/v1/pos/reports/salesSales summary
Query parameters
| Parameter | Type | Description |
|---|---|---|
date_fromrequired | string | ISO date. e.g. 2026-03-01. |
date_torequired | string | ISO date. e.g. 2026-03-31. |
group_by | string | "day" | "week" | "month". Default: "day". |
curl "https://api.xeboki.com/v1/pos/reports/sales?date_from=2026-03-01&date_to=2026-03-31" \
-H "Authorization: Bearer xbk_live_..."Response 200
{
"summary": {
"total_orders": 312,
"total_revenue_cents": 458200,
"average_order_cents": 1468,
"top_products": [
{ "product_id": "prod_abc123", "name": "Margherita Pizza", "qty_sold": 84, "revenue_cents": 109116 }
]
},
"series": [
{ "date": "2026-03-01", "orders": 12, "revenue_cents": 17400 }
]
}https://api.xeboki.com/v1/pos/reports/daily/{date}Daily totals
End-of-day summary for a specific date. date format: YYYY-MM-DD.
curl "https://api.xeboki.com/v1/pos/reports/daily/2026-03-31" \
-H "Authorization: Bearer xbk_live_..."Error codes
All errors return JSON with a detail field.
| Status | Meaning | Common cause |
|---|---|---|
400 | Bad Request | Missing field, invalid product ID, out-of-stock item in order |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | Key lacks required pos:* scope, or subscription inactive |
404 | Not Found | Product, order, or customer not found in your store |
409 | Conflict | Customer email already registered |
422 | Unprocessable | Item no longer in stock, coupon expired or already used |
429 | Rate Limited | Too many requests — back off and retry |
502 | Bad Gateway | POS service temporarily unavailable |
{ "detail": "Item 'prod_abc123' is out of stock." }