developer_tools.public_docs_home developer_tools.public_api_reference
developer_tools.subtitle
developer_tools.nav_module_settings
Settings endpoints cover invoice schemes and layouts, barcode presets, notification templates, receipt printers, business settings, integration webhooks, and business locations. Unless a section says otherwise, CSV exports ignore pagination and write endpoints follow the same permission and demo-mode rules as the matching web settings screen.
Lists invoice numbering schemes that the token user can manage from Invoice settings.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/invoice-schemes |
| Permission | invoice_settings.access. |
| Search behavior | q requires at least 2 characters when sent. Legacy search still matches name, prefix, or numeric id. |
| CSV behavior | format=csv downloads all matching rows as UTF-8 CSV with BOM and ignores page and per_page. |
| Success response | 200 with paginated rows or a CSV download. |
| Parameter | Type | Required | Description |
|---|---|---|---|
per_page, page | integer | No | Pagination controls. per_page accepts 1 to 100 and defaults to 20. |
q, search | string | No | Text search across scheme name, prefix, and numeric id-like values. |
sort | string | No | name, scheme_type, number_type, invoice_count, or created_at. |
direction | string | No | asc or desc. |
format | string | No | json (default) or csv. |
| Field | Type | Description |
|---|---|---|
id, name | integer | string | Scheme identity and display name. |
scheme_type | string | blank or year. |
number_type | string | sequential or random. |
invoice_count, is_default | integer | boolean | Current usage counter and default flag. |
prefix_preview | string | null | Current-year preview when scheme_type = year. |
| Field | Type | Description |
|---|---|---|
data | array<object> | The current result page of invoice schemes. |
meta.current_page, meta.last_page, meta.per_page, meta.total | integer | Laravel paginator metadata. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice schemes were returned successfully. | { "data": [...], "meta": { ... } } or CSV download. |
403 | The token user lacks invoice_settings.access. | { "message": string } |
422 | The query string failed validation. | Laravel validation JSON. |
Returns one invoice scheme and can flatten the same payload into a single CSV row.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/invoice-schemes/{id} |
| Permission | invoice_settings.access. |
| CSV behavior | format=csv streams one UTF-8 BOM row whose data_json cell matches the JSON data object. |
| Success response | 200 with one invoice-scheme object. |
| Parameter | Type | Required | Description |
|---|---|---|---|
format | string | No | json (default) or csv. CSV download name: invoice-scheme-{id}-detail-{business_id}-{timestamp}.csv. |
| Field | Type | Description |
|---|---|---|
name, prefix | string | null | Saved scheme name and optional invoice prefix. |
scheme_type, number_type | string | The numbering strategy used by this scheme. |
total_digits, start_number | integer | null | Sequential-number configuration. start_number is omitted for random schemes. |
invoice_count, is_default | integer | boolean | Current counter and whether the scheme is the business default. |
| Field | Type | Description |
|---|---|---|
data | object | The requested invoice-scheme payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice scheme was returned successfully. | { "data": { ... } } or CSV download. |
403 | The token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice scheme id does not exist for the current business. | { "message": "Not found" } |
Creates a new invoice numbering scheme and can optionally make it the default for the business.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/invoice-schemes |
| Permission | invoice_settings.access. |
| Default behavior | When is_default = true, the previous business default is cleared before the new scheme is marked default. |
| Write guard | Returns 403 in demo environments. |
| Success response | 201 with the created invoice-scheme object. |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the scheme. |
scheme_type | string | Yes | blank or year. |
number_type | string | Yes | sequential or random. |
prefix | string | null | No | Optional invoice prefix. |
total_digits | integer | null | No | Optional numeric width for generated invoice numbers. |
start_number | integer | null | Conditional | Required for sequential schemes. Omit or send null for random numbering. |
is_default | boolean | No | When true, this scheme becomes the new business default. |
| Field | Type | Description |
|---|---|---|
data | object | The created invoice-scheme payload. |
| Status | When it happens | Response shape |
|---|---|---|
201 | The invoice scheme was created successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
422 | The request body failed validation. | Laravel validation JSON. |
Updates an existing invoice scheme without changing which scheme is the current default.
| Property | Value |
|---|---|
| Method | PATCH or PUT |
| Path | /api/v1/integration/invoice-schemes/{id} |
| Permission | invoice_settings.access. |
| Write rule | Uses the same field rules as create, except is_default is not accepted here. Use Set default instead. |
| Counter rule | invoice_count is read-only and is only changed when invoices are issued. |
| Success response | 200 with the updated invoice-scheme object. |
| Field | Type | Required | Description |
|---|---|---|---|
All Add invoice scheme fields except is_default | mixed | No | Send only the values that should change. |
| Field | Type | Description |
|---|---|---|
data | object | The updated invoice-scheme payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice scheme was updated successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice scheme id does not exist for the current business. | { "message": "Not found" } |
422 | The request body failed validation. | Laravel validation JSON. |
Marks one invoice scheme as default and clears the default flag from all other schemes in the same business.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/invoice-schemes/{id}/set-default |
| Permission | invoice_settings.access. |
| Write guard | Returns 403 in demo environments. |
| Success response | 200 with the refreshed invoice-scheme object. |
| Field | Type | Description |
|---|---|---|
data | object | The invoice scheme after the default flag is updated. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice scheme became the business default. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice scheme id does not exist for the current business. | { "message": "Not found" } |
Deletes an invoice scheme that is not the active default and is not referenced by any business location.
| Property | Value |
|---|---|
| Method | DELETE |
| Path | /api/v1/integration/invoice-schemes/{id} |
| Permission | invoice_settings.access. |
| Business rule | Returns 422 when the scheme is the current default or is referenced by a location as invoice_scheme_id or sale_invoice_scheme_id. |
| Write guard | Returns 403 in demo environments. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice scheme was deleted successfully. | { "message": string } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice scheme id does not exist for the current business. | { "message": "Not found" } |
422 | The scheme is default or is still referenced by one or more locations. | { "message": string } |
Lists printable invoice layouts exactly as they appear under Invoice settings in the web UI.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/invoice-layouts |
| Permission | invoice_settings.access. |
| Search behavior | q requires at least 2 characters when sent. Legacy search still matches layout name or numeric id. |
| CSV behavior | format=csv downloads all matching rows. Array and object fields are JSON-encoded in CSV cells. |
| Success response | 200 with paginated rows or a CSV download. |
| Parameter | Type | Required | Description |
|---|---|---|---|
per_page, page | integer | No | Pagination controls. per_page accepts 1 to 100 and defaults to 20. |
q, search | string | No | Text search across layout name or numeric id-like values. |
sort | string | No | name, design, is_default, or created_at. |
direction | string | No | asc or desc. |
format | string | No | json (default) or csv. |
| Field | Type | Description |
|---|---|---|
id, name, design | mixed | Layout identity and design template name. |
is_default | boolean | Whether the layout is the current business default. |
show_* flags | boolean | Print toggles copied from the web Invoice layouts form. |
module_info, common_settings | object | array | null | Structured printable settings stored with the layout. |
logo_url, letter_head_url | string | null | Resolved asset URLs when the uploaded files exist. |
| Field | Type | Description |
|---|---|---|
data | array<object> | The current result page of invoice layouts. |
meta.current_page, meta.last_page, meta.per_page, meta.total | integer | Laravel paginator metadata. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice layouts were returned successfully. | { "data": [...], "meta": { ... } } or CSV download. |
403 | The token user lacks invoice_settings.access. | { "message": string } |
422 | The query string failed validation. | Laravel validation JSON. |
Returns one invoice layout, including its printable flags and uploaded asset URLs.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/invoice-layouts/{id} |
| Permission | invoice_settings.access. |
| CSV behavior | format=csv streams one UTF-8 BOM row whose data_json cell matches the JSON data object. |
| Success response | 200 with one invoice-layout object. |
| Parameter | Type | Required | Description |
|---|---|---|---|
format | string | No | json (default) or csv. CSV download name: invoice-layout-{id}-detail-{business_id}-{timestamp}.csv. |
| Field | Type | Description |
|---|---|---|
name, design | string | Layout name and selected print design. |
Printable labels and show_* flags | mixed | All user-configured print labels and boolean display toggles from the web form. |
module_info, table_tax_headings, product_custom_fields, contact_custom_fields, location_custom_fields, common_settings, qr_code_fields | object | array | null | Structured layout settings stored as arrays or objects. |
logo_url, letter_head_url | string | null | Resolved image URLs when uploaded assets exist. |
| Field | Type | Description |
|---|---|---|
data | object | The requested invoice-layout payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice layout was returned successfully. | { "data": { ... } } or CSV download. |
403 | The token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice layout id does not exist for the current business. | { "message": "Not found" } |
Creates a new printable invoice layout, including optional uploaded logo and letterhead images passed as data URLs.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/invoice-layouts |
| Permission | invoice_settings.access. |
| Content type | application/json. |
| Default behavior | When is_default = true, the previous business default is cleared before this layout is marked default. |
| Write guard | Returns 403 in demo environments. |
| Success response | 201 with the created invoice-layout object. |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the layout. |
design | string | Yes | classic, elegant, detailed, columnize-taxes, slim, slim2, or english-arabic. |
Printable labels and show_* flags | mixed | No | Optional label overrides and boolean print toggles from the web Invoice layouts form. |
module_info, table_tax_headings, product_custom_fields, contact_custom_fields, location_custom_fields, common_settings, qr_code_fields | object | array | null | No | Structured layout settings sent as arrays or objects. |
is_default | boolean | No | When true, this layout becomes the new business default. |
logo_base64, letter_head_base64 | string | null | No | Optional image data URLs such as data:image/png;base64,.... |
| Field | Type | Description |
|---|---|---|
data | object | The created invoice-layout payload. |
| Status | When it happens | Response shape |
|---|---|---|
201 | The invoice layout was created successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
422 | The request body failed validation. | Laravel validation JSON. |
Partially updates an invoice layout while preserving any fields that are not included in the request.
| Property | Value |
|---|---|
| Method | PATCH or PUT |
| Path | /api/v1/integration/invoice-layouts/{id} |
| Permission | invoice_settings.access. |
| Write rule | Send only the fields that should change. Default selection is handled by Set default. |
| Image rule | New logo or letterhead uploads use logo_base64 and letter_head_base64 data URLs. |
| Success response | 200 with the updated invoice-layout object. |
| Field | Type | Required | Description |
|---|---|---|---|
All Add invoice layout fields except is_default | mixed | No | All update fields are optional and are applied partially. |
| Field | Type | Description |
|---|---|---|
data | object | The updated invoice-layout payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice layout was updated successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice layout id does not exist for the current business. | { "message": "Not found" } |
422 | The request body failed validation. | Laravel validation JSON. |
Marks one invoice layout as default for the business.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/invoice-layouts/{id}/set-default |
| Permission | invoice_settings.access. |
| Write guard | Returns 403 in demo environments. |
| Success response | 200 with the refreshed invoice-layout object. |
| Field | Type | Description |
|---|---|---|
data | object | The invoice layout after the default flag is updated. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice layout became the business default. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice layout id does not exist for the current business. | { "message": "Not found" } |
Deletes an invoice layout that is neither the current default nor referenced by a business location.
| Property | Value |
|---|---|
| Method | DELETE |
| Path | /api/v1/integration/invoice-layouts/{id} |
| Permission | invoice_settings.access. |
| Business rule | Returns 422 when the layout is the current default or is referenced by a location as invoice_layout_id or sale_invoice_layout_id. |
| Write guard | Returns 403 in demo environments. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The invoice layout was deleted successfully. | { "message": string } |
403 | Demo mode is active or the token user lacks invoice_settings.access. | { "message": string } |
404 | The invoice layout id does not exist for the current business. | { "message": "Not found" } |
422 | The layout is default or is still referenced by one or more locations. | { "message": string } |
Lists saved barcode presets exactly as they appear in Barcode settings.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/barcode-presets |
| Permission | barcode_settings.access. |
| Search behavior | q requires at least 2 characters when sent. Legacy search still matches preset name, description, or numeric id. |
| CSV behavior | format=csv downloads all matching rows as UTF-8 CSV with BOM and ignores pagination. |
| Success response | 200 with paginated rows or a CSV download. |
| Parameter | Type | Required | Description |
|---|---|---|---|
per_page, page | integer | No | Pagination controls. per_page accepts 1 to 100 and defaults to 20. |
q, search | string | No | Text search across preset name, description, and numeric id-like values. |
sort | string | No | name, is_default, or created_at. |
direction | string | No | asc or desc. |
format | string | No | json (default) or csv. |
| Field | Type | Description |
|---|---|---|
id, name, description | mixed | Preset identity and display values. |
width, height, paper_width, paper_height | number | null | Saved label and paper dimensions. |
is_continuous, is_default | boolean | Continuous-roll behavior and default flag. |
stickers_in_one_row, stickers_in_one_sheet | integer | null | Sheet layout settings. Continuous presets force stickers_in_one_sheet = 28. |
| Field | Type | Description |
|---|---|---|
data | array<object> | The current result page of barcode presets. |
meta.current_page, meta.last_page, meta.per_page, meta.total | integer | Laravel paginator metadata. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The barcode presets were returned successfully. | { "data": [...], "meta": { ... } } or CSV download. |
403 | The token user lacks barcode_settings.access. | { "message": string } |
422 | The query string failed validation. | Laravel validation JSON. |
Returns one barcode preset and can flatten the same payload into a single CSV row.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/barcode-presets/{id} |
| Permission | barcode_settings.access. |
| CSV behavior | format=csv streams one UTF-8 BOM row whose data_json cell matches the JSON data object. |
| Success response | 200 with one barcode-preset object. |
| Parameter | Type | Required | Description |
|---|---|---|---|
format | string | No | json (default) or csv. CSV download name: barcode-preset-{id}-detail-{business_id}-{timestamp}.csv. |
| Field | Type | Description |
|---|---|---|
name, description | string | null | Preset label and optional description. |
| Dimension and margin fields | number | null | Width, height, paper size, and margin settings used for label rendering. |
stickers_in_one_row, stickers_in_one_sheet | integer | null | Sheet layout settings used during barcode printing. |
is_continuous, is_default | boolean | Continuous-roll behavior and default status. |
| Field | Type | Description |
|---|---|---|
data | object | The requested barcode-preset payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The barcode preset was returned successfully. | { "data": { ... } } or CSV download. |
403 | The token user lacks barcode_settings.access. | { "message": string } |
404 | The barcode preset id does not exist for the current business. | { "message": "Not found" } |
Creates a barcode preset that can later be reused from barcode print flows and preview endpoints.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/barcode-presets |
| Permission | barcode_settings.access. |
| Continuous rule | When is_continuous = true, the controller forces stickers_in_one_sheet = 28. |
| Default behavior | When is_default = true, the previous business default is cleared first. |
| Success response | 201 with the created barcode-preset object. |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the preset. |
description | string | null | No | Optional helper text for the preset. |
width, height, paper_width, paper_height, top_margin, left_margin, row_distance, col_distance | number | null | No | Optional dimension and margin fields. |
stickers_in_one_row, stickers_in_one_sheet | integer | null | No | Optional sheet layout settings. |
is_continuous, is_default | boolean | No | Optional continuous-roll and default flags. |
| Field | Type | Description |
|---|---|---|
data | object | The created barcode-preset payload. |
| Status | When it happens | Response shape |
|---|---|---|
201 | The barcode preset was created successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks barcode_settings.access. | { "message": string } |
422 | The request body failed validation. | Laravel validation JSON. |
Partially updates a barcode preset and re-applies the same continuous-roll rules used by the web form.
| Property | Value |
|---|---|
| Method | PATCH or PUT |
| Path | /api/v1/integration/barcode-presets/{id} |
| Permission | barcode_settings.access. |
| Continuous rule | When is_continuous is sent, continuous presets force stickers_in_one_sheet = 28 and paper_height = 0. |
| Write mode | All update fields are optional and are merged with the current preset. |
| Success response | 200 with the updated barcode-preset object. |
| Field | Type | Required | Description |
|---|---|---|---|
| All Add barcode preset fields | mixed | No | Send only the values that should change. |
| Field | Type | Description |
|---|---|---|
data | object | The updated barcode-preset payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The barcode preset was updated successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks barcode_settings.access. | { "message": string } |
404 | The barcode preset id does not exist for the current business. | { "message": "Not found" } |
422 | The request body failed validation. | Laravel validation JSON. |
Marks one barcode preset as the business default.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/barcode-presets/{id}/set-default |
| Permission | barcode_settings.access. |
| Write guard | Returns 403 in demo environments. |
| Success response | 200 with the refreshed barcode-preset object. |
| Field | Type | Description |
|---|---|---|
data | object | The barcode preset after the default flag is updated. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The barcode preset became the business default. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks barcode_settings.access. | { "message": string } |
404 | The barcode preset id does not exist for the current business. | { "message": "Not found" } |
Deletes a barcode preset that is not currently marked as default.
| Property | Value |
|---|---|
| Method | DELETE |
| Path | /api/v1/integration/barcode-presets/{id} |
| Permission | barcode_settings.access. |
| Business rule | Returns 422 when the preset is the current default. |
| Write guard | Returns 403 in demo environments. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The barcode preset was deleted successfully. | { "message": string } |
403 | Demo mode is active or the token user lacks barcode_settings.access. | { "message": string } |
404 | The barcode preset id does not exist for the current business. | { "message": "Not found" } |
422 | The preset is still marked as the business default. | { "message": string } |
Builds the same HTML label preview used by the Print labels screen without creating any printable transaction records.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/barcode-labels/preview |
| Permission | barcode_settings.access. |
| Preset rule | barcode_setting_id may reference a business preset or a global preset whose business_id is null. |
| Generation limit | The sum of all requested sticker quantities is capped at 5000, and the request may include at most 200 product rows. |
| Success response | 200 with rendered preview HTML and metadata. |
| Field | Type | Required | Description |
|---|---|---|---|
barcode_setting_id | integer | Yes | The barcode preset id to render against. |
products | array<object> | Yes | Preview rows containing variation_id, quantity, and optional price_group_id, exp_date, packing_date, and lot_number. |
print | object | null | No | Optional label overrides matching the Print labels form keys such as name, name_size, price, price_size, and price_type. |
Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json Accept: application/json
| Field | Type | Description |
|---|---|---|
data.format | string | Always html for preview responses. |
data.html | string | Rendered tables and inline styles matching the web preview. |
data.meta.pages, data.meta.total_stickers | integer | Preview page count and total sticker count. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The barcode preview was generated successfully. | { "data": { "format": "html", "html": string, "meta": { ... } } } |
403 | The token user lacks barcode_settings.access. | { "message": string } |
404 | The barcode preset id does not exist or is not visible. | { "message": "Not found" } |
422 | The request body failed validation, a variation is invalid, a price group is invalid, or preview generation failed. | Laravel validation JSON or { "message": string }. |
Lists the notification-template catalog grouped the same way as the web Notification templates screen.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/notification-templates |
| Permission | send_notification. |
| Grouping | Templates are grouped into general, customer, and supplier buckets, plus any module-provided notification hooks. |
| CSV behavior | format=csv downloads one row per template in the same JSON order. There is no pagination. |
| Success response | 200 with grouped template arrays or a CSV download. |
| Parameter | Type | Required | Description |
|---|---|---|---|
group | string | No | general, customer, supplier, or all (default). |
format | string | No | json (default) or csv. |
| Field | Type | Description |
|---|---|---|
group, template_for, name | string | Template grouping and internal identity key. |
subject, email_body, sms_body, whatsapp_text | string | null | Saved content fields for each notification channel. |
auto_send, auto_send_sms, auto_send_wa_notif | boolean | Auto-send flags used by the template. |
cc, bcc | string | null | Saved CC and BCC addresses. |
extra_tags, id | array | integer | null | Merge-tag hints and the database id when a stored row exists. |
| Field | Type | Description |
|---|---|---|
data.general, data.customer, data.supplier | array<object> | null | Template arrays for the requested groups. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The notification-template catalog was returned successfully. | { "data": { ... } } or CSV download. |
403 | The token user lacks send_notification. | { "message": string } |
422 | The query string failed validation. | Laravel validation JSON. |
Returns one notification template by its internal template_for key.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/notification-templates/{template_for} |
| Permission | send_notification. |
| Identifier | template_for is the internal catalog key such as new_sale or payment_reminder. |
| CSV behavior | format=csv streams one UTF-8 BOM row with the same columns as the list endpoint. |
| Success response | 200 with one notification-template object. |
| Parameter | Type | Required | Description |
|---|---|---|---|
format | string | No | json (default) or csv. CSV download name: notification-template-{template_for}-{business_id}-{timestamp}.csv. |
| Field | Type | Description |
|---|---|---|
data | object | The requested template payload, matching the list-row shape. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The notification template was returned successfully. | { "data": { ... } } or CSV download. |
403 | The token user lacks send_notification. | { "message": string } |
404 | The requested template_for key is not present in the catalog for this business. | { "message": "Not found" } |
Saves multiple notification templates in one request using the same field names as the web bulk editor.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/notification-templates |
| Permission | send_notification. |
| Content type | application/json. |
| Write guard | Returns 403 in demo environments. |
| Success response | 200 with the list of template keys that were saved. |
| Field | Type | Required | Description |
|---|---|---|---|
template_data | object | Yes | Object keyed by template_for. Each nested object may contain subject, email_body, sms_body, whatsapp_text, auto_send, auto_send_sms, auto_send_wa_notif, cc, and bcc. |
| Field | Type | Description |
|---|---|---|
updated | array<string> | The list of template keys that were saved. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The notification templates were saved successfully. | { "updated": [...] } |
403 | Demo mode is active or the token user lacks send_notification. | { "message": string } |
422 | The request body failed validation or contains unknown template keys. | Laravel validation JSON. |
Partially updates a single notification template while leaving omitted fields unchanged.
| Property | Value |
|---|---|
| Method | PATCH |
| Path | /api/v1/integration/notification-templates/{template_for} |
| Permission | send_notification. |
| Write rule | Omitted fields keep their current values from NotificationTemplate::getTemplate. |
| Write guard | Returns 403 in demo environments. |
| Success response | 200 with the refreshed notification-template object. |
| Field | Type | Required | Description |
|---|---|---|---|
subject, email_body, sms_body, whatsapp_text | string | null | No | Optional content fields to update. |
auto_send, auto_send_sms, auto_send_wa_notif | boolean | No | Optional auto-send flags. |
cc, bcc | string | null | No | Optional email address fields. |
| Field | Type | Description |
|---|---|---|
data | object | The updated template payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The notification template was updated successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks send_notification. | { "message": string } |
404 | The requested template_for key is not present in the catalog for this business. | { "message": "Not found" } |
422 | The request body failed validation. | Laravel validation JSON. |
Lists receipt printers configured for the business together with connection-type metadata used by the printer settings screen.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/receipt-printers |
| Permission | access_printers. |
| Search behavior | q requires at least 2 characters when sent. Legacy search still matches printer name, IP, path, or numeric id. |
| CSV behavior | format=csv downloads all matching rows. JSON-only metadata stays in the normal response. |
| Success response | 200 with paginated rows plus meta.connection_types and meta.capability_profiles. |
| Parameter | Type | Required | Description |
|---|---|---|---|
per_page, page | integer | No | Pagination controls. per_page accepts 1 to 100 and defaults to 20. |
q, search | string | No | Text search across printer identity fields. |
sort | string | No | name, connection_type, capability_profile, or created_at. |
direction | string | No | asc or desc. |
format | string | No | json (default) or csv. |
| Field | Type | Description |
|---|---|---|
id, name | integer | string | Printer identity and display name. |
connection_type, connection_type_label | string | Stored connection code and human-readable label. |
capability_profile, capability_profile_label | string | Capability profile code and label. |
ip_address, port, path, char_per_line | mixed | Connection details used for printing. |
| Field | Type | Description |
|---|---|---|
data | array<object> | The current result page of receipt printers. |
meta.connection_types, meta.capability_profiles | object | Choice maps returned only on JSON responses. |
meta.current_page, meta.last_page, meta.per_page, meta.total | integer | Laravel paginator metadata. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The receipt printers were returned successfully. | { "data": [...], "meta": { ... } } or CSV download. |
403 | The token user lacks access_printers. | { "message": string } |
422 | The query string failed validation. | Laravel validation JSON. |
Returns one receipt printer together with the same connection-type metadata used by the printer settings UI.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/receipt-printers/{id} |
| Permission | access_printers. |
| CSV behavior | format=csv streams one row with data_json and meta_json cells matching the JSON payload. |
| Success response | 200 with one printer object and metadata maps. |
| Parameter | Type | Required | Description |
|---|---|---|---|
format | string | No | json (default) or csv. CSV download name: receipt-printer-{id}-detail-{business_id}-{timestamp}.csv. |
| Field | Type | Description |
|---|---|---|
data | object | The requested receipt-printer payload. |
meta.connection_types, meta.capability_profiles | object | Choice maps returned together with the printer record. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The receipt printer was returned successfully. | { "data": { ... }, "meta": { ... } } or CSV download. |
403 | The token user lacks access_printers. | { "message": string } |
404 | The receipt printer id does not exist for the current business. | { "message": "Not found" } |
Creates a receipt printer with the same network or local-path rules used by the web form.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/receipt-printers |
| Permission | access_printers. |
| Network rule | When connection_type = network, send ip_address and port. Local path is cleared. |
| Local rule | When connection_type = windows or linux, send path. IP and port are cleared. |
| Success response | 201 with the created printer object, including created_by. |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the printer. |
connection_type | string | Yes | network, windows, or linux. |
capability_profile | string | Yes | default, simple, SP2000, TEP-200M, or P822D. |
ip_address, port | mixed | Conditional | Required for network printers. |
path | string | null | Conditional | Required for Windows and Linux printers. |
char_per_line | integer | null | No | Optional printer width hint. |
| Field | Type | Description |
|---|---|---|
data | object | The created receipt-printer payload. |
| Status | When it happens | Response shape |
|---|---|---|
201 | The receipt printer was created successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks access_printers. | { "message": string } |
422 | The request body failed validation. | Laravel validation JSON. |
Partially updates a receipt printer and re-applies the same connection rules after merging the new fields.
| Property | Value |
|---|---|
| Method | PATCH or PUT |
| Path | /api/v1/integration/receipt-printers/{id} |
| Permission | access_printers. |
| Write rule | All update fields are optional and are merged with the existing printer before connection rules are re-applied. |
| Success response | 200 with the updated receipt-printer object. |
| Field | Type | Required | Description |
|---|---|---|---|
| All Add receipt printer fields | mixed | No | Send only the values that should change. |
| Field | Type | Description |
|---|---|---|
data | object | The updated receipt-printer payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The receipt printer was updated successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks access_printers. | { "message": string } |
404 | The receipt printer id does not exist for the current business. | { "message": "Not found" } |
422 | The request body failed validation. | Laravel validation JSON. |
Deletes a receipt printer that is not currently referenced by any business location.
| Property | Value |
|---|---|
| Method | DELETE |
| Path | /api/v1/integration/receipt-printers/{id} |
| Permission | access_printers. |
| Business rule | Returns 422 when a location still uses the printer as printer_id. |
| Write guard | Returns 403 in demo environments. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The receipt printer was deleted successfully. | { "message": string } |
403 | Demo mode is active or the token user lacks access_printers. | { "message": string } |
404 | The receipt printer id does not exist for the current business. | { "message": "Not found" } |
422 | The printer is still assigned to one or more locations. | { "message": string } |
Returns the business settings row together with the same date-format metadata used by the web Business settings screen.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/business-settings |
| Permission | business_settings.access. |
| CSV behavior | format=csv streams one row with data_json and meta_json cells matching the JSON payload. |
| Sensitive-field rule | woocommerce_api_settings is never returned in the response. |
| Success response | 200 with the business-settings object and date-format metadata. |
| Field | Type | Description |
|---|---|---|
data | object | The business row with decoded JSON fields such as pos_settings, keyboard_shortcuts, and custom_labels. |
meta.date_formats | object | Allowed business date-format keys from Business::date_formats(). |
| Status | When it happens | Response shape |
|---|---|---|
200 | The business settings were returned successfully. | { "data": { ... }, "meta": { ... } } or CSV download. |
403 | The token user lacks business_settings.access. | { "message": string } |
Partially updates business settings using the same merge semantics as the web Business settings form.
| Property | Value |
|---|---|
| Method | PATCH or PUT |
| Path | /api/v1/integration/business-settings |
| Permission | business_settings.access. |
| Merge rule | pos_settings is merged with the current value and defaults. shortcuts is stored as keyboard_shortcuts. |
| Upload rule | business_logo_base64 accepts an image data URL. POS carousel images are not uploaded through this API. |
| Success response | 200 with the same response shape as GET. |
| Field | Type | Required | Description |
|---|---|---|---|
| General business fields and feature toggles | mixed | No | Includes booleans such as enable_rp, enable_tooltip, and purchase_in_diff_currency. |
pos_settings | object | No | Partial POS settings object merged with the current value. |
shortcuts | array | No | Keyboard shortcut definitions stored as keyboard_shortcuts. |
business_logo_base64 | string | null | No | Optional business logo image data URL. |
| Field | Type | Description |
|---|---|---|
data | object | The updated business-settings payload. |
meta.date_formats | object | Allowed business date-format keys. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The business settings were updated successfully. | { "data": { ... }, "meta": { ... } } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
422 | The request body failed validation. | Laravel validation JSON. |
Lists integration webhooks configured for the business, together with the allowed event catalog used by the web settings page.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/webhooks |
| Permission | business_settings.access. |
| Filter support | Supports pagination plus an optional is_active boolean filter. |
| CSV behavior | format=csv downloads all matching rows. events is JSON-encoded in CSV cells. |
| Success response | 200 with paginated rows and meta.allowed_events. |
| Parameter | Type | Required | Description |
|---|---|---|---|
per_page, page | integer | No | Pagination controls. per_page accepts 1 to 100 and defaults to 20. |
is_active | boolean | No | Optional active/inactive filter. |
format | string | No | json (default) or csv. |
| Field | Type | Description |
|---|---|---|
id, url, description | mixed | Webhook identity and destination details. |
events | array<string> | The subscribed event names for this endpoint. |
is_active, secret_set | boolean | Whether the webhook is enabled and whether a signing secret is stored. |
created_by, created_at, updated_at | mixed | Audit metadata for the webhook row. |
| Field | Type | Description |
|---|---|---|
data | array<object> | The current result page of webhooks. |
meta.allowed_events | array<string> | The event names that can be subscribed on create and update. |
meta.current_page, meta.last_page, meta.per_page, meta.total | integer | Laravel paginator metadata. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The webhooks were returned successfully. | { "data": [...], "meta": { ... } } or CSV download. |
403 | The token user lacks business_settings.access. | { "message": string } |
422 | The query string failed validation. | Laravel validation JSON. |
Returns one integration webhook together with the same allowed-event metadata used by the settings page.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/webhooks/{id} |
| Permission | business_settings.access. |
| CSV behavior | format=csv streams one row with data_json and meta_json cells matching the JSON payload. |
| Success response | 200 with one webhook object and the allowed-event list. |
| Field | Type | Description |
|---|---|---|
data | object | The requested webhook payload. |
meta.allowed_events | array<string> | The event names that may be subscribed. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The webhook was returned successfully. | { "data": { ... }, "meta": { ... } } or CSV download. |
403 | The token user lacks business_settings.access. | { "message": string } |
404 | The webhook id does not exist for the current business. | { "message": "Not found" } |
Creates an integration webhook that can receive sale and low-stock event deliveries.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/webhooks |
| Permission | business_settings.access. |
| Supported events | sale.created, sale.updated, and product.stock_low. |
| Signing rule | When secret is present, deliveries include X-Webhook-Signature: sha256=<hex> over the raw JSON body. |
| Success response | 201 with the created webhook object. |
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Destination URL. HTTPS is recommended. |
events | array<string> | Yes | Non-empty list of allowed event names. |
description | string | null | No | Optional human-readable description. |
secret | string | null | No | Optional signing secret with a minimum length of 8 characters. |
is_active | boolean | No | Optional active flag. Defaults to true. |
| Event | When it fires | Payload notes |
|---|---|---|
sale.created | When a final sell is saved for the first time. | Uses the same SellCreatedOrModified event pipeline as the rest of the app. |
sale.updated | When an existing final sell is modified. | Uses the same sale event pipeline as create. |
product.stock_low | When tracked quantity crosses from above the alert threshold to at or below it. | Payload includes variation_id, product_id, location_id, product_name, qty_available, and alert_quantity. |
| Field | Type | Description |
|---|---|---|
data | object | The created webhook payload. |
| Status | When it happens | Response shape |
|---|---|---|
201 | The webhook was created successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
422 | The request body failed validation. | Laravel validation JSON. |
Partially updates a webhook's destination, subscribed events, secret, or active state.
| Property | Value |
|---|---|
| Method | PATCH |
| Path | /api/v1/integration/webhooks/{id} |
| Permission | business_settings.access. |
| Write mode | All update fields are optional and are applied partially. |
| Success response | 200 with the updated webhook object. |
| Field | Type | Required | Description |
|---|---|---|---|
url, description, secret | string | null | No | Optional destination, description, and signing-secret updates. |
events | array<string> | No | Optional full replacement for the subscribed event list. |
is_active | boolean | No | Optional active-state update. |
| Field | Type | Description |
|---|---|---|
data | object | The updated webhook payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The webhook was updated successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
404 | The webhook id does not exist for the current business. | { "message": "Not found" } |
422 | The request body failed validation. | Laravel validation JSON. |
Deletes an integration webhook.
| Property | Value |
|---|---|
| Method | DELETE |
| Path | /api/v1/integration/webhooks/{id} |
| Permission | business_settings.access. |
| Write guard | Returns 403 in demo environments. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The webhook was deleted successfully. | { "message": string } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
404 | The webhook id does not exist for the current business. | { "message": "Not found" } |
Queues a single webhook.test delivery so you can validate connectivity before turning a webhook on.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/webhooks/{id}/test |
| Permission | business_settings.access. |
| Behavior | The test run still works when the webhook itself is marked inactive. |
| Write guard | Returns 403 in demo environments. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The test delivery was queued successfully. | { "message": string } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
404 | The webhook id does not exist for the current business. | { "message": "Not found" } |
Lists business locations visible to the token user, including receipt and invoice defaults resolved for display.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/business-locations |
| Permission | business_settings.access. |
| Visibility | Users with restricted location access only see permitted locations. |
| CSV behavior | format=csv downloads all matching rows and ignores pagination. |
| Success response | 200 with paginated rows or a CSV download. |
| Parameter | Type | Required | Description |
|---|---|---|---|
per_page, page | integer | No | Pagination controls. |
q, search | string | No | Search across location name, location id, city, landmark, territory/cluster names and reference_code values, and numeric id-like values. |
is_active | boolean | No | Optional active/inactive filter. |
sort | string | No | name, location_id, city, or created_at. |
direction | string | No | asc or desc. |
format | string | No | json (default) or csv. |
| Field | Type | Description |
|---|---|---|
id, name, location_id | mixed | Location identity and display values. |
territory_id, territory_reference_code, territory_name, location_cluster_id, cluster_reference_code, cluster_name | mixed | Hierarchy fields when a location is linked to a territory and/or cluster. |
territory, cluster | object | null | Compact nested objects with id, reference_code, name (cluster also includes territory_id) for integrations. |
invoice_scheme_name, invoice_layout_name, selling_price_group_name | string | null | Resolved related-setting labels. |
print_receipt_on_invoice, receipt_printer_type, printer_id, printer_name | mixed | Receipt-printing configuration returned in list rows. |
is_active | boolean | Current active state for the location. |
| Field | Type | Description |
|---|---|---|
data | array<object> | The current result page of business locations. |
meta.current_page, meta.last_page, meta.per_page, meta.total | integer | Laravel paginator metadata. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The business locations were returned successfully. | { "data": [...], "meta": { ... } } or CSV download. |
403 | The token user lacks business_settings.access. | { "message": string } |
422 | The query string failed validation. | Laravel validation JSON. |
Returns one business location with full detail, including default payment accounts and featured products when configured.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/business-locations/{id} |
| Permission | business_settings.access plus location visibility. |
| CSV behavior | format=csv streams one row whose data_json cell matches the JSON data object. |
| Success response | 200 with one business-location object. |
| Field | Type | Description |
|---|---|---|
data | object | The requested business-location payload, including nested fields such as default_payment_accounts and featured_products when present. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The business location was returned successfully. | { "data": { ... } } or CSV download. |
403 | The location exists but is outside the token user's permitted locations. | { "message": string } |
404 | The business location id does not exist for the current business. | { "message": "Not found" } |
Returns every territory for the business with optional reference_code (unique per business) for stable integration identifiers.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/territories |
| Permission | business_settings.access. |
| Success response | 200 with { "data": [ { "id", "reference_code", "name", "description", "created_at", "updated_at" } ] }. |
Returns clusters with parent territory id, name, and reference codes so callers can resolve location_cluster_id / territory_id on locations.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/location-clusters |
| Permission | business_settings.access. |
| Success response | 200 with { "data": [ { "id", "reference_code", "name", "description", "territory_id", "territory_name", "territory_reference_code", "created_at", "updated_at" } ] }. |
Returns the enabled payment-method keys and translated labels for one business location.
| Property | Value |
|---|---|
| Method | GET |
| Path | /api/v1/integration/business-locations/{id}/payment-types |
| Permission | No separate settings permission. The location must belong to the business and be within the token user's permitted locations. |
| CSV behavior | format=csv streams one row per payment method with the same shape as JSON data[]. |
| Success response | 200 with payment-type rows and meta.location_id. |
| Field | Type | Description |
|---|---|---|
data[] | array<object> | Rows with key and label for each enabled payment method. |
meta.location_id | integer | The resolved business-location id. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The payment types were returned successfully. | { "data": [...], "meta": { "location_id": integer } } or CSV download. |
403 | The location exists but is outside the token user's permitted locations. | { "message": string } |
404 | The business location id does not exist for the current business. | { "message": "Not found" } |
Creates a business location, auto-generates its location code when omitted, and validates the same linked settings as the web form.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/business-locations |
| Permission | business_settings.access. |
| Subscription rule | Returns 402 when the business is not subscribed and 422 when the location quota is exhausted. |
| Reference rule | When location_id is omitted, the controller auto-generates it and creates the matching Spatie permission location.{id}. |
| Success response | 201 with the created business-location object. |
| Field | Type | Required | Description |
|---|---|---|---|
| Core location fields | mixed | Yes | Standard location identity and address fields such as name, optional location_id, and contact details. |
territory_id, location_cluster_id | integer | null | No | Optional link to a territory and cluster belonging to the business; cluster must sit under its territory. |
invoice_scheme_id, invoice_layout_id, selling_price_group_id | integer | null | No | Optional related-setting ids that must belong to the current business. |
default_payment_accounts | object | null | No | Optional default payment-account mapping object. |
featured_products | array<integer> | null | No | Optional list of variation ids highlighted at the location. |
| Receipt settings | mixed | No | Optional receipt-printing fields such as print_receipt_on_invoice, receipt_printer_type, and printer_id. |
| Field | Type | Description |
|---|---|---|
data | object | The created business-location payload. |
| Status | When it happens | Response shape |
|---|---|---|
201 | The business location was created successfully. | { "data": { ... } } |
402 | The business subscription does not allow creating locations. | { "message": string } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
422 | The request body failed validation or the business has reached its location quota. | Laravel validation JSON or { "message": string }. |
Partially updates a business location, including receipt-printer settings and invoice defaults.
| Property | Value |
|---|---|
| Method | PATCH |
| Path | /api/v1/integration/business-locations/{id} |
| Permission | business_settings.access. |
| Uniqueness rule | location_id must remain unique per business when it is updated. |
| Receipt rule | Receipt fields follow LocationSettingsController::updateSettings. In demo mode, sending receipt fields forces receipt_printer_type = browser. |
| Success response | 200 with the updated business-location object. |
| Field | Type | Required | Description |
|---|---|---|---|
| All Create business location fields | mixed | No | All update fields are optional and are applied partially. |
print_receipt_on_invoice, receipt_printer_type, printer_id | mixed | No | Receipt-printing settings validated against the current business and printer catalog. |
| Field | Type | Description |
|---|---|---|
data | object | The updated business-location payload. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The business location was updated successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
404 | The business location id does not exist for the current business. | { "message": "Not found" } |
422 | The request body failed validation. | Laravel validation JSON. |
Flips a business location between active and inactive states, mirroring the web activate/deactivate action.
| Property | Value |
|---|---|
| Method | POST |
| Path | /api/v1/integration/business-locations/{id}/toggle-active |
| Permission | business_settings.access. |
| Write guard | Returns 403 in demo environments. |
| Success response | 200 with the refreshed business-location object. |
| Status | When it happens | Response shape |
|---|---|---|
200 | The business location active state was toggled successfully. | { "data": { ... } } |
403 | Demo mode is active or the token user lacks business_settings.access. | { "message": string } |
404 | The business location id does not exist for the current business. | { "message": "Not found" } |