Point of Sale
Point of Sale
Tables and open tabs for on-location selling. A tab is a running order, not a document: it carries no number, is never fiscalized and holds no payments. It becomes an invoice through the normal POST /invoices flow.
The lifecycle of a tab is:
1. POST /pos/tabs opens one, optionally on a table.
2. POST /pos/tabs/{id}/items adds to it. Appends to an open tab are additive: concurrent additions serialize and merge quantities on matching lines. New appends return 409 already_claimed while a payment claim is active. Retrying a previously accepted append_id returns the current tab without adding the items again.
3. POST /pos/tabs/{id}/claim reserves it for one device before payment, so a second device cannot issue the same tab and produce a duplicate invoice and duplicate fiscal record. Claims expire after five minutes.
4. Issue the invoice however you normally would, then POST /pos/tabs/{id}/close with the invoice_id. Close is idempotent, which is what makes a lost response after a successful issue recoverable.
Edits and removals use PATCH /pos/tabs/{id} with expected_version and get a 409 carrying the current tab if another device changed it first.
To keep devices in a venue in sync, poll GET /pos/tabs and send the previous ETag back as If-None-Match; an unchanged venue answers 304.
The Point of Sale object
Attributes
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "open",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 2,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": null,
"version": 3,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}Create a point-of-sale table
/pos/tablesCreate a point-of-sale table
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Body parameters
Table name as staff refer to it — "1", "12", "Terrace 3".
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.createTable({
label: "4",
sort_order: 4
});
console.log(response);Returns
{
"id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"label": "4",
"sort_order": 4,
"is_active": true,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T18:00:00.000Z",
"updated_at": "2026-07-31T18:00:00.000Z"
}Open a tab
/pos/tabsOpen a tab
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.createTab({
table_id: "ptbl_65f1a2b3c4d5e6f7a8b9c0d1"
});
console.log(response);Returns
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "open",
"items": [],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": null,
"version": 1,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}Switch the acting operator
/pos/operators/switchVerifies the PIN and returns a shift-length token for that member, so the sales they ring up carry their own fiscal operator identity. Requires an existing valid session for the same entity. Repeated failures lock the PIN with an escalating backoff.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.switchOperator({
user_id: "usr_65f1a2b3c4d5e6f7a8b9c0d8",
pin: "482"
});
console.log(response);Returns
Bearer token for the switched-to operator.
{
"id": "tok_65f1a2b3c4d5e6f7a8b9c0da",
"user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d8",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"ttl": 43200,
"scope": "pos_operator",
"created_at": "2026-07-31T20:25:00.000Z"
}List point-of-sale tables
/pos/tablesList point-of-sale tables
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Query parameters
Include deactivated tables.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.listTables();
console.log(response);Returns
{
"data": [
{
"id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"label": "1",
"sort_order": 1,
"is_active": true,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T18:00:00.000Z",
"updated_at": "2026-07-31T18:00:00.000Z"
},
{
"id": "ptbl_65f1a2b3c4d5e6f7a8b9c0e1",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"label": "2",
"sort_order": 2,
"is_active": true,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T18:00:00.000Z",
"updated_at": "2026-07-31T18:00:00.000Z"
},
{
"id": "ptbl_65f1a2b3c4d5e6f7a8b9c0e2",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"label": "Terrace 1",
"sort_order": 3,
"is_active": true,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T18:00:00.000Z",
"updated_at": "2026-07-31T18:00:00.000Z"
}
]
}List point-of-sale tabs
/pos/tabsReturns the full set of tabs in the requested statuses. Send the previous ETag back as If-None-Match to get a 304 when nothing changed — this is the intended polling path for keeping devices in a venue in sync.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
ETag from a previous response. Returns 304 when the tab set is unchanged.
Query parameters
Comma-separated statuses to include. Defaults to open and issuing.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.listTabs();
console.log(response);Returns
{
"data": [
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "open",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 2,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": null,
"version": 3,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}
]
}Daily takings
/pos/reports/dailyWhat the venue took on one day, split by payment type, tax rate, item category and operator.
This is a business report, not a fiscal one: Slovenia and Croatia confirm every cash invoice with the authority as it is issued, so there is no daily close to file and nothing here is submitted anywhere. Voided documents are counted separately and excluded from the totals. Operator attribution comes from the fiscal record, which is where the acting operator is stored.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Query parameters
The day to report on, by document date.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.dailyReport({
date: "2026-08-15"
});
console.log(response);Returns
{
"date": "2026-08-15",
"currency_code": "EUR",
"totals": {
"invoices": 42,
"voided": 1,
"net": 1011.89,
"tax": 222.61,
"gross": 1234.5
},
"by_payment_type": [
{
"type": "cash",
"invoices": 30,
"total": 800
},
{
"type": "card",
"invoices": 12,
"total": 434.5
}
],
"by_tax_rate": [
{
"rate": 22,
"base": 1011.89,
"amount": 222.61
}
],
"by_category": [
{
"category": "wine",
"quantity": 61,
"total": 700
},
{
"category": "food",
"quantity": 24,
"total": 534.5
}
],
"by_operator": [
{
"operator": "Ana",
"invoices": 42,
"total": 1234.5
}
]
}List staff who can operate this point of sale
/pos/operatorsList staff who can operate this point of sale
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.listOperators();
console.log(response);Returns
{
"data": [
{
"user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"name": "Ana",
"email": "ana@winebar.example",
"role": "admin",
"has_pin": true
},
{
"user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d8",
"name": "Luka",
"email": "luka@winebar.example",
"role": "editor",
"has_pin": false
}
]
}Get a tab
/pos/tabs/{id}Get a tab
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.getTab("inv_6595a27b5d35015c3ef0c3fd");
console.log(response);Returns
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "open",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 2,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": null,
"version": 3,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}Update a point-of-sale table
/pos/tables/{id}Update a point-of-sale table
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.updateTable("inv_6595a27b5d35015c3ef0c3fd", {
label: "Terrace 1",
sort_order: 7
});
console.log(response);Returns
{
"id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"label": "Terrace 1",
"sort_order": 7,
"is_active": true,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T18:00:00.000Z",
"updated_at": "2026-07-31T18:00:00.000Z"
}Replace a tab's contents
/pos/tabs/{id}Replacing write for edits and removals, guarded by expected_version. A 409 means another device changed the tab first and carries the current tab.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
Body parameters
Version the client last saw. The request is rejected with 409 if the tab changed since, and the response carries the current tab.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.updateTab("inv_6595a27b5d35015c3ef0c3fd", {
items: [
{
line_id: "line_7f3a",
item_id: "item_65f1a2b3c4d5e6f7a8b9c0d3",
name: "Glass of red wine",
quantity: 2,
unit_gross_price: 5.5,
discount_percent: null,
tax_rates: null,
note: null,
added_by_user_id: "usr_65f1a2b3c4d5e6f7a8b9c0d4",
added_at: "2026-07-31T20:12:00.000Z"
}
],
expected_version: 3
});
console.log(response);Returns
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "open",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 2,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": null,
"version": 4,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}Set an operator PIN
/pos/operators/{user_id}/pinSets the PIN used to switch to this member on a shared device. Callers may set their own PIN; entity admins may set anyone's. The PIN identifies who is acting, it does not grant access: the device must already hold a valid session for the same entity. Exactly three digits, so a till can act on the last one without a confirm step.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Body parameters
Exactly three digits.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.setOperatorPin('USER_ID', {
pin: "482"
});
console.log(response);Delete a point-of-sale table
/pos/tables/{id}Delete a point-of-sale table
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
await sdk.pointOfSale.deleteTable("inv_6595a27b5d35015c3ef0c3fd");
console.log('Deleted successfully');Cancel a tab
/pos/tabs/{id}Send expected_version when cancelling because the tab looked empty: a poll-based view can be seconds stale, and without the guard a round another device just added would be discarded. Omit it to cancel regardless, which is what an operator picking "Cancel tab" means.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
Query parameters
Refuse with 409 unless the tab is still at this version.
Remove an operator PIN
/pos/operators/{user_id}/pinRemove an operator PIN
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
await sdk.pointOfSale.clearOperatorPin('USER_ID');
console.log('Deleted successfully');Add items to a tab
/pos/tabs/{id}/itemsAppends to an open tab are additive: concurrent additions serialize and merge quantities on matching lines. New appends return 409 already_claimed while a payment claim is active. Retrying a previously accepted append_id returns the current tab without adding the items again.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
Body parameters
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.appendTabItems("inv_6595a27b5d35015c3ef0c3fd", {
items: [
{
line_id: "line_7f3a",
item_id: "item_65f1a2b3c4d5e6f7a8b9c0d3",
name: "Glass of red wine",
quantity: 2,
unit_gross_price: 5.5,
discount_percent: null,
tax_rates: null,
note: null,
added_by_user_id: "usr_65f1a2b3c4d5e6f7a8b9c0d4",
added_at: "2026-07-31T20:12:00.000Z"
}
]
});
console.log(response);Returns
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "open",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 4,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": null,
"version": 4,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}Reserve a tab for payment
/pos/tabs/{id}/claimMarks the tab as being paid on one device so a second device cannot issue it at the same time, which would produce a duplicate invoice and a duplicate fiscal record. Claims expire after five minutes so a crashed device cannot lock a table.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
Body parameters
Stable per-device identifier, so the claiming device can recognise its own claim after a restart.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.claimTab("inv_6595a27b5d35015c3ef0c3fd", {
device_id: "9C2E5F10-7A44-4E0B-9D2C-1B8E3A6F0C41"
});
console.log(response);Returns
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "issuing",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 2,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": "9C2E5F10-7A44-4E0B-9D2C-1B8E3A6F0C41",
"claimed_at": "2026-07-31T20:20:00.000Z",
"invoice_id": null,
"version": 4,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}Release a payment claim
/pos/tabs/{id}/releaseHands a claimed tab back. Only the device holding the claim may release it — otherwise the claim would be decorative, since any device could free a tab another is paying and take it over. An expired claim may be cleared by anyone.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
Body parameters
The device releasing the claim. Must match the device holding it unless the claim has expired.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.releaseTab("inv_6595a27b5d35015c3ef0c3fd", {
device_id: "9C2E5F10-7A44-4E0B-9D2C-1B8E3A6F0C41"
});
console.log(response);Returns
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "open",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 2,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": null,
"version": 5,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": null,
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}Close a tab against an issued invoice
/pos/tabs/{id}/closeIdempotent: re-closing a tab with the same invoice returns it unchanged. This is what makes a lost response after a successful issue recoverable rather than stranding the table.
Header parameters
Entity ID on which the request is made. Auto-selected when only one entity exists, required when multiple entities exist.
Path parameters
Unique resource identifier
Body parameters
Invoice the tab was issued as.
import SpaceInvoices from '@spaceinvoices/js-sdk/sdk';
const sdk = new SpaceInvoices('YOUR_API_KEY');
const response = await sdk.pointOfSale.closeTab("inv_6595a27b5d35015c3ef0c3fd", {
invoice_id: "inv_65f1a2b3c4d5e6f7a8b9c0d9"
});
console.log(response);Returns
{
"id": "ptab_65f1a2b3c4d5e6f7a8b9c0d5",
"entity_id": "ent_65f1a2b3c4d5e6f7a8b9c0d2",
"table_id": "ptbl_65f1a2b3c4d5e6f7a8b9c0d1",
"status": "issued",
"items": [
{
"line_id": "line_7f3a",
"item_id": "item_65f1a2b3c4d5e6f7a8b9c0d3",
"name": "Glass of red wine",
"quantity": 2,
"unit_gross_price": 5.5,
"discount_percent": null,
"tax_rates": null,
"note": null,
"added_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"added_at": "2026-07-31T20:12:00.000Z"
}
],
"note": null,
"customer_id": null,
"opened_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"updated_by_user_id": "usr_65f1a2b3c4d5e6f7a8b9c0d4",
"claimed_by_device": null,
"claimed_at": null,
"invoice_id": "inv_65f1a2b3c4d5e6f7a8b9c0d9",
"version": 5,
"opened_at": "2026-07-31T20:05:00.000Z",
"issued_at": "2026-07-31T20:22:00.000Z",
"metadata": {},
"deleted_at": null,
"created_at": "2026-07-31T20:05:00.000Z",
"updated_at": "2026-07-31T20:12:00.000Z"
}