POS → Noovi
Use the registered POS client ID and certificate. Noovi checks the company in the URL and the operation’s scope.
Examples use placeholder hosts and IDs. Use your assigned API address and credentials for live requests.
Register the POS receiver URL and map one Noovi company to one POS location.
https://pos.example.test/v1 serves multiple companies.https://demo.pos.example.test/v1 serves one company.For either URL, validate X-Noovi-Company-Id against the token before routing to the POS location. Agree on the location ID, supported order types, and whether orders are sent at confirmation or after payment.
Use OAuth 2.0 client credentials with mutual TLS. Obtain a short-lived token from the Noovi issuer and send it with the same client certificate on each request. Certificate-bound tokens
Use the registered POS client ID and certificate. Noovi checks the company in the URL and the operation’s scope.
Use the receiver’s assigned audience and trusted Noovi signing keys. Refresh keys on rotation and match the verified company to the request header and location.
curl 'https://auth.noovi.example.test/oauth/token' \
--cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode "client_id=$PARTNER_CLIENT_ID" \
--data-urlencode 'scope=tables:read'
The Noovi API audience is urn:noovi:pos:api. Validate JWT type, issuer, signature, audience, expiry, certificate thumbprint, company, and scope. If TLS terminates at a gateway, use the certificate identity verified by that gateway. JWT validation
NOOVI_BASE='https://noovi.example.test/api/pos/v1'
POS_BASE='https://pos.example.test/v1'
COMPANY_ID='cmp_demo'
Use NOOVI_TOKEN for the Noovi API and POS_TOKEN for the POS receiver. Each token needs the operation’s scope and matching certificate.
Pick an operation and run its sample, or enter your test URL and token for a live request.
POS → Noovi
GET/companies/{companyId}/tables
Use tables:read. A table with posTableId: null is available to map.
curl "$NOOVI_BASE/companies/$COMPANY_ID/tables" \
--cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
-H "Authorization: Bearer $NOOVI_TOKEN"
PUT/companies/{companyId}/tables/{posTableId}
Use tables:write and a stable POS table ID. Pass resourceId on the first request to link an existing Noovi table, or send a name and capacity to create one. Noovi manages booking-type eligibility separately.
curl -X PUT "$NOOVI_BASE/companies/$COMPANY_ID/tables/table-12" \
--cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
-H "Authorization: Bearer $NOOVI_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"name":"Table 12","capacity":4,"resourceId":"R-RSC-DEMO12"}'
PUT/companies/{companyId}/tables/{posTableId}/status
Use tables:write. Send available, occupied, or unavailable with the UTC observation time. Exact repeats succeed. Stale updates or a different state at the same time return 409.
curl -X PUT "$NOOVI_BASE/companies/$COMPANY_ID/tables/table-12/status" \
--cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
-H "Authorization: Bearer $NOOVI_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"state":"occupied","observedAt":"2026-11-09T23:30:00Z"}'
Noovi tracks POS observations separately from host-stand arrival, seating, departure, and clearing.
GET/companies/{companyId}/reservations
Use reservations:read with a UTC from/to window. Filter by posTableId if needed. Results include reservation state and party state. posTableId is null until a table is assigned and mapped.
curl --get "$NOOVI_BASE/companies/$COMPANY_ID/reservations" \
--cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
-H "Authorization: Bearer $NOOVI_TOKEN" \
--data-urlencode 'from=2026-11-09T22:00:00Z' \
--data-urlencode 'to=2026-11-10T04:00:00Z'
Noovi → POS
POST/orders
Noovi calls the receiver with orders:write. Validate company, location, and item IDs, then return the POS order ID. Dine-in orders include a mapped table and may include a reservation ID.
The POS records paid as already collected and collects payment for unpaid orders. The payload covers item lines and tax. Agree on an extension for modifiers, discounts, tips, or extra fees.
curl "$POS_BASE/orders" \
--cert "$NOOVI_CERT" --key "$NOOVI_KEY" \
-H "Authorization: Bearer $POS_TOKEN" \
-H "X-Noovi-Company-Id: $COMPANY_ID" \
-H "Idempotency-Key: $COMPANY_ID:ORD-DEMO-001" \
-H 'Content-Type: application/json' --data-binary @- <<'JSON'
{
"orderId": "ORD-DEMO-001",
"locationId": "loc_demo",
"fulfillment": { "type": "pickup" },
"paymentStatus": "paid",
"items": [{ "itemId": "menu-01", "quantity": 2, "unitPriceMinor": 1200 }],
"currency": "USD",
"amounts": { "subtotalMinor": 2400, "taxMinor": 192, "totalMinor": 2592 }
}
JSON
{
"orderId": "ORD-DEMO-001",
"posOrderId": "pos-987",
"locationId": "loc_demo"
}
201 after durable creation, 200 with the same receipt on replay, and 409 if the same key has a different payload.Retry-After. Fix authentication, location, and item mapping errors before retrying.GET/orders/by-reference/{orderId}
After a timeout, Noovi checks the receipt with orders:read. A retry uses the original payload and idempotency key.
POS → Noovi
Guest exchange is optional. Enable imports and approved exports separately for each company and partner.
PUT/companies/{companyId}/guests/{posGuestId}
Use guests:write, a stable POS guest ID, and an international phone number. Names and email are optional. Mapping is scoped to the company and connection. An existing-guest conflict returns 409 for review.
curl -X PUT "$NOOVI_BASE/companies/$COMPANY_ID/guests/guest-42" \
--cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
-H "Authorization: Bearer $NOOVI_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"firstName":"Morgan","phoneNumber":"+12025550173"}'
GET/companies/{companyId}/guests
Use guests:read. Read data.guests and pass data.nextCursor as cursor. Keep guestId as the source reference. A POS guest ID is returned if this partner already has a mapping.
curl --get "$NOOVI_BASE/companies/$COMPANY_ID/guests" \
--cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
-H "Authorization: Bearer $NOOVI_TOKEN" \
--data-urlencode 'limit=100'