Noovi Developers API console

POS API reference

Examples use placeholder hosts and IDs. Use your assigned API address and credentials for live requests.

Endpoint index

Connection setup

Register the POS receiver URL and map one Noovi company to one POS location.

Shared URL
https://pos.example.test/v1 serves multiple companies.
Per-company URL
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.

Authentication

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

POS → Noovi

Use the registered POS client ID and certificate. Noovi checks the company in the URL and the operation’s scope.

Noovi → POS

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.

Request a token for reading Noovi tables curl
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

  • Use separate client identities and certificates by company, direction, and environment. Keep private keys on the caller and support rotation and revocation.
  • Check object ownership on every operation. Enable guest read and write access separately and audit access. Object authorization
  • Check registered HTTPS destinations at connection time and disable redirects. Outbound request controls
  • Log request IDs and outcomes. Exclude tokens, private keys, and full guest payloads.
Example request variables bash
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.

Try a request

Pick an operation and run its sample, or enter your test URL and token for a live request.

POS → Noovi

Tables and reservations

List physical tables

Try it

GET/companies/{companyId}/tables

Use tables:read. A table with posTableId: null is available to map.

Request curl
curl "$NOOVI_BASE/companies/$COMPANY_ID/tables" \
  --cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
  -H "Authorization: Bearer $NOOVI_TOKEN"

Map a POS table

Try it

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.

Link an existing table curl
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"}'

Report POS table status

Try it

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.

Report an occupied table curl
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.

Read reservation status

Try it

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.

Read bookings for a service window curl
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

Orders

Create an order

Try it

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.

Request curl
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
201 Created JSON
{
  "orderId": "ORD-DEMO-001",
  "posOrderId": "pos-987",
  "locationId": "loc_demo"
}
201 / 200 / 409
Return 201 after durable creation, 200 with the same receipt on replay, and 409 if the same key has a different payload.
429 / 503
Noovi backs off and honors Retry-After. Fix authentication, location, and item mapping errors before retrying.

Look up an order receipt

Try it

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

Guests

Guest exchange is optional. Enable imports and approved exports separately for each company and partner.

Import a POS guest

Try it

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.

Request curl
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"}'

Retrieve approved Noovi guests

Try it

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.

First page curl
curl --get "$NOOVI_BASE/companies/$COMPANY_ID/guests" \
  --cert "$PARTNER_CERT" --key "$PARTNER_KEY" \
  -H "Authorization: Bearer $NOOVI_TOKEN" \
  --data-urlencode 'limit=100'

Integration checklist

  • Send a valid token with the wrong certificate, audience, company, and scope. Confirm the receiver rejects each case before accessing any data.
  • Run two test companies against one shared receiver. Confirm each request resolves to the correct location and uses its own menu.
  • Map an existing table and register a new one. Replay a stale status update and verify a POS observation leaves the host’s seating and cleaning state intact.
  • Send one order twice with the same key. Simulate a dropped response and verify that lookup and replay return the same POS order ID.
  • Confirm that the POS records a paid order without collecting again and handles an unpaid order using the agreed POS payment flow.
  • If guest exchange is enabled, verify import, conflicts, pagination, export eligibility, and independent read and write permissions.