API referenceTenvelo API
https://api.tenvelo.com The contract, as OpenAPI

Contract 2026-10-10. Every path below carries its own major version.

Merchant · Reference

Locations

Shops, stalls and vans.

Operations
7
Base
https://api.tenvelo.com
  1. GET/v1/franchise-report-share

    What the brand may see

    No. getFranchiseReportShareAuth no token

    What this business lets its brand read — whether the brand's reports across its franchisees may show this business's figures (locations and groups, item 18). A merchant with no brand is 404: there is nothing to share. The figures themselves are derived on read from this business's own data, never copied (0119); this answers only the grant.

    Responses

    • 200

      The grant, as it stands.

      FranchiseReportShare · application/json
      • brand_idstring · uuid

        Required

        The brand this business is a franchisee of, read-only on the merchant (0008).

      • brand_namestring

        Required

        How the brand calls itself, for the franchisee's own screens.

      • sharingboolean

        Required

        Whether the brand may read this business's figures (locations and groups, item 18). Nothing is shared until the owner grants it, and the grant is revoked on any of the brand's reports. This answer is what a franchisee's own screens show as "waiting for the owner" until it is set.

      • versionVersion

        RequiredRead only

        Optimistic concurrency version, raised by the server on every write. A version is never lower than one already returned for the resource, though it may rise by more than one.

        Returned in the ETag response header as well as in the body. Send it back in If-Match on an update and the write is rejected with 412 if anyone else has written since — which is what stops two tills silently overwriting each other's edit to the same product when both come back online at once.

        ≥ 1

    • 400

      The request could not be parsed. Malformed JSON, a bad query parameter, or a header that failed to decode, among them an API-Version later than the server speaks or not a date (api-version-unknown, with the server's own in api_version).

      Distinct from 422: a 400 never reached validation, so invalid_params is absent. Retrying without changing the request will fail again, except that a request refused for its API-Version goes once the server is updated.

    • 401

      No credentials, or credentials that could not be verified — missing bearer token, malformed JWT, expired token, or a signature that failed against the issuer's JWKS.

      Refresh the token and retry once. Repeated 401 after a refresh means the device needs to re-enrol.

    • 403

      Authenticated, but not permitted. The token is valid and its merchant was resolved, but the caller's role does not allow this operation, or the target belongs to a different merchant.

      Cross-tenant access is reported as 403 on a resource the caller may not see, and as 404 where even confirming existence would leak information. Retrying will not help.

    • 404

      No such resource, or none visible to this caller.

      Also returned instead of 403 where acknowledging existence would itself leak information — so a 404 does not prove the id is unused globally, only that it is not yours.

    • 410

      The request names an API-Version this server no longer serves (docs/decisions/0011). Nothing in it was read. api_version names the version the server speaks: the client is behind, and sends the request again once it is updated.

    • 429

      Rate limit exceeded. Honour Retry-After rather than applying your own backoff.

      A fleet of tills coming back online together after an outage is the realistic cause, which is exactly when uncoordinated client-side retry turns a brief outage into a sustained one. The limit is per process, and per site for what records trade there — a request spends its site's budget, and a till's own smaller one inside it — and per (client, merchant) for everything else; no RateLimit field is sent, so this response and its Retry-After are the whole of the contract.

    • 500

      Something failed on our side. trace_id identifies the request in our tracing — quote it in a support ticket.

      The body never carries internal detail: no SQL, no stack traces, no upstream error strings. Safe to retry with the same Idempotency-Key.

    • 503

      Temporarily unable to serve the request — a dependency is down or the service is shedding load.

      Retry with the same Idempotency-Key after Retry-After. This is always safe: a request that did take effect before the failure will be recognised as a replay.

  2. PATCH/v1/franchise-report-share

    Decide what the brand may see

    No. updateFranchiseReportShareAuth merchant:write

    The owner granting or withdrawing the brand's read of this business's figures (locations and groups, item 18; docs/design/back-office/franchisees.html — each franchisee "as its owner lets the brand see it"). A manager cannot: letting figures out of the business is the owner's alone. The change is a fact on the business's own stream, and the grant's projection is its only writer. A merge patch, guarded by If-Match against the grant's version: a change made against a version somebody has since changed is refused with 412.

    Parameters

    • If-Matchheader · string

      Required

      The ETag from the read that produced the value you are updating.

      Required on updates, not optional, because "last write wins" is the wrong default for a catalogue two managers might edit at once. If anything has been written since your read, the request is rejected with 412 and you re-read and re-apply.

      Use * to mean "write regardless of current version" — an explicit, greppable override rather than the silent default.

    Request body application/merge-patch+json

    • sharingboolean

      Required

      What the brand may read: true grants, false revokes.

    Responses

    • 200

      The grant, as it stands after the change.

      FranchiseReportShare · application/json
      • brand_idstring · uuid

        Required

        The brand this business is a franchisee of, read-only on the merchant (0008).

      • brand_namestring

        Required

        How the brand calls itself, for the franchisee's own screens.

      • sharingboolean

        Required

        Whether the brand may read this business's figures (locations and groups, item 18). Nothing is shared until the owner grants it, and the grant is revoked on any of the brand's reports. This answer is what a franchisee's own screens show as "waiting for the owner" until it is set.

      • versionVersion

        RequiredRead only

        Optimistic concurrency version, raised by the server on every write. A version is never lower than one already returned for the resource, though it may rise by more than one.

        Returned in the ETag response header as well as in the body. Send it back in If-Match on an update and the write is rejected with 412 if anyone else has written since — which is what stops two tills silently overwriting each other's edit to the same product when both come back online at once.

        ≥ 1

    • 400

      The request could not be parsed. Malformed JSON, a bad query parameter, or a header that failed to decode, among them an API-Version later than the server speaks or not a date (api-version-unknown, with the server's own in api_version).

      Distinct from 422: a 400 never reached validation, so invalid_params is absent. Retrying without changing the request will fail again, except that a request refused for its API-Version goes once the server is updated.

    • 401

      No credentials, or credentials that could not be verified — missing bearer token, malformed JWT, expired token, or a signature that failed against the issuer's JWKS.

      Refresh the token and retry once. Repeated 401 after a refresh means the device needs to re-enrol.

    • 403

      Authenticated, but not permitted. The token is valid and its merchant was resolved, but the caller's role does not allow this operation, or the target belongs to a different merchant.

      Cross-tenant access is reported as 403 on a resource the caller may not see, and as 404 where even confirming existence would leak information. Retrying will not help.

    • 404

      No such resource, or none visible to this caller.

      Also returned instead of 403 where acknowledging existence would itself leak information — so a 404 does not prove the id is unused globally, only that it is not yours.

    • 410

      The request names an API-Version this server no longer serves (docs/decisions/0011). Nothing in it was read. api_version names the version the server speaks: the client is behind, and sends the request again once it is updated.

    • 412

      The If-Match version did not match the resource's current version: someone else wrote since you read.

      This is the expected, healthy outcome of two clients editing the same record — not an error condition to suppress. Re-read the resource, re-apply your change on top of the new state, and retry with the fresh ETag.

    • 422

      The request parsed but failed validation.

      invalid_params lists every failing field with a JSON Pointer, not just the first, so a client can mark up a whole form in one pass rather than making the user fix errors one round trip at a time.

      Also returned when an Idempotency-Key is replayed with a different body, and when device-computed order totals disagree with the server's recomputation.

    • 429

      Rate limit exceeded. Honour Retry-After rather than applying your own backoff.

      A fleet of tills coming back online together after an outage is the realistic cause, which is exactly when uncoordinated client-side retry turns a brief outage into a sustained one. The limit is per process, and per site for what records trade there — a request spends its site's budget, and a till's own smaller one inside it — and per (client, merchant) for everything else; no RateLimit field is sent, so this response and its Retry-After are the whole of the contract.

    • 500

      Something failed on our side. trace_id identifies the request in our tracing — quote it in a support ticket.

      The body never carries internal detail: no SQL, no stack traces, no upstream error strings. Safe to retry with the same Idempotency-Key.

    • 503

      Temporarily unable to serve the request — a dependency is down or the service is shedding load.

      Retry with the same Idempotency-Key after Retry-After. This is always safe: a request that did take effect before the failure will be recognised as a replay.

  3. GET/v1/locations

    List locations

    No. listLocationsAuth bearer

    Returns the merchant's locations.

    Parameters

    • cursorquery · string

      Opaque cursor from a previous page's next_cursor. Omit to start from the beginning.

      Pass it back exactly as received. It is base64 and its structure is not part of this contract — decoding it, or constructing one by hand, will break without notice.

    • limitquery · integer · int32

      Maximum items to return. The server may return fewer, so always drive the loop from has_more rather than from the size of the page you got back.

    Responses

    • 200

      A page of locations.

      LocationPage · application/json
      • has_moreboolean

        Required

        Whether another page follows.

      • itemsarray of Location

        Required

        • idstring · uuid

          Required

          UUIDv7 identifying the location.

        • typestring · enum

          Required

          mobile locations — market stalls, food vans — are expected to spend meaningful time offline, and are the reason the sync contract exists.

          physicalmobile

        • namestring

          Required

          Human-readable name, unique within the merchant. Appears in the dashboard and on receipts.

          1–255 chars

        • addressAddress

          A postal address.

          The address_line_* fields carry the most specific part of the address — street number, street name, building name. Less specific detail belongs in locality, administrative_district_level_* and country.

          The administrative_district_level_* fields are deliberately generic because their meaning is country-dependent: in the US level 1 is the state and level 2 the county; in the UK level 1 is the county.

          • address_line_1string

            Required

            First line of the address — street number, street name, building name.

            ≤ 255 chars

          • address_line_2string

            Second line of the address, if any.

            ≤ 255 chars

          • address_line_3string

            Third line of the address, if any.

            ≤ 255 chars

          • administrative_district_level_1string

            A civil entity within the country. The state in the US; the county in the UK.

            ≤ 128 chars

          • administrative_district_level_2string

            A civil entity within administrative_district_level_1.

            ≤ 128 chars

          • countryCountry

            Required

            ISO 3166-1 alpha-2 country code.

            ZZ is the unknown/unspecified placeholder.

            One of 250 values; see the schema.

          • localitystring

            The city or town.

            ≤ 128 chars

          • postal_codestring

            The postal or ZIP code.

            ≤ 32 chars

          • sublocalitystring

            A civil region within the locality, if any.

            ≤ 128 chars

        • auto_close_default_tip_percentagePercentage

          A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

          A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

        • auto_close_enabledboolean

          On, when this location's day closes, every open tab holding a card is settled with auto_close_default_tip_percentage; a tab with no card is left open and flagged left-overnight (tabs item 9).

        • booking_hoursarray of DaypartWindow

          The hours this location takes bookings, in its own timezone. Empty takes none. Absent from a write leaves them as they are.

          ≤ 28 items

          • daysarray of integer

            The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

            ≤ 7 items

          • end_minuteinteger

            Required

            1–1440

          • start_minuteinteger

            Required

            0–1439

        • break_threshold_minutesinteger · int32

          How long a shift at this location may run before a break is expected, in minutes. Zero disables the rule. Replaces the hard-coded six hours in the timesheet.

          ≥ 0 · default 360

        • business_day_start_local_timestring

          When this location's trading day begins, as a wall-clock time in its timezone (RFC 3339 partial-time, in the shape Square uses for start_local_time). A sale before it belongs to the previous business day, so a bar's 00:30 round counts towards last night's takings rather than today's.

          Defaults to 04:00, as Toast's closeout hour does: nothing that opens before four in the morning is affected, and every late-night venue is. Changing it affects sales from then on; days already traded keep the business date they were given.

          pattern ^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$ · default 04:00:00

        • business_emailstring · email

          The address a guest's reply to an email this venue sent should reach: the Reply-To on the guest messages this location's emails send. Empty means a reply goes to the platform, which answers for the venue.

          ≤ 254 chars

        • business_hoursarray of DaypartWindow

          The hours this location trades, in its own timezone, which the marketplace shows as open or closed. Apart from booking_hours. Absent from a write leaves them as they are.

          ≤ 8 items

          • daysarray of integer

            The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

            ≤ 7 items

          • end_minuteinteger

            Required

            1–1440

          • start_minuteinteger

            Required

            0–1439

        • cash_stepMoney

          A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

          The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

          Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • coordinatesCoordinates

          Nullable

          Where the location is, placed by the merchant, which the marketplace sorts guests' results by. null until placed. Absent from a write leaves it as it is.

          • latitudenumber · double

            Required

            -90–90

          • longitudenumber · double

            Required

            -180–180

        • created_atTimestamp

          RequiredRead only

          Server-assigned RFC 3339 timestamp, always UTC.

          Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

        • descriptionstring

          What the location says about itself on the marketplace. Absent from a write leaves it as it is.

          ≤ 280 chars

        • favoritesarray of string · uuid

          A shop's favourites, Square's Favorites and Toast's speed menu: up to twenty-four of its products, in this order, which a till in retail shows first, before the catalogue. Empty means the catalogue alone. Chosen in the back office; a device never writes it.

          ≤ 24 items · default []

        • kds_amber_minutesinteger · int32

          How long a kitchen ticket may wait (in minutes) before a kitchen display colours it amber. A location setting; the till paints from it.

          ≥ 1 · default 10

        • kds_red_minutesinteger · int32

          How long a kitchen ticket may wait (in minutes) before a kitchen display colours it red. A location setting; the till paints from it.

          ≥ 1 · default 20

        • labor_budgetMoney

          Nullable

          What a week's labor here is planned to cost, which the rota compares against. null sets none. Absent from a write leaves it as it is.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • labor_target_percentagePercentage

          Nullable

          What labor here should cost as a share of net sales, which Home and the labor report set the day's cost against. null sets none. Absent from a write leaves it as it is.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

        • language_codeLanguageCode

          IETF BCP 47 language tag.

          Used for receipts, dashboard copy and buyer-facing text.

          One of 30 values; see the schema.

        • merchant_idstring · uuid

          RequiredRead only

          The owning merchant. Read-only and derived from the caller's token — a location can never be moved between merchants.

        • min_break_minutesinteger · int32

          The least a break that is taken should be, in minutes. A shift with a break shorter than this still counts as missed.

          ≥ 0 · default 0

        • online_bookingOnlineBooking

          Whether guests may book this location themselves on its booking page, how far ahead and for how many, and how much of the room is kept for walk-ins. Absent from a write leaves it as it is.

          • days_aheadinteger · int32

            Required

            0–365

          • deposit_per_personMoney

            A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

            The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

            Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

            • amountinteger · int64

              Required

              The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

            • currencyCurrency

              Required

              ISO 4217 currency code.

              Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

              One of 182 values; see the schema.

          • enabledboolean

            Required

          • max_party_sizeinteger · int32

            Required

            The largest party a guest may book online. 0 is no limit.

            0–100

          • waitlist_enabledboolean

            Whether guests may join this location's waitlist from its own page. Distinct from enabled: a venue may take bookings online and not queue walk-ins from the web, or queue them and take no bookings. Absent from a write leaves it as it is.

          • walk_in_percentagePercentage

            Required

            A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

            A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

            pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

        • ordering_auto_acceptboolean

          Read only

          Whether an order from the ordering page is accepted as it arrives, rather than waiting for somebody to take it on. Changed on the ordering settings, not by writing the location.

          default false

        • ordering_enabledboolean

          Read only

          Whether guests can order from this location's ordering page. Changed on the ordering settings, not by writing the location.

          default false

        • ordering_handlestring

          Read only

          The ordering page's name: its subdomain on the guest ordering site. Absent until one is chosen. Changed on the ordering settings, not by writing the location.

          ≤ 63 chars

        • ordering_pausedboolean

          When true, a channel's new open orders are refused — the kitchen could not take another one. The till keeps selling regardless, and the setting is carried on the change feed so every surface hears it without a poll.

          default false

        • ordering_prep_time_minutesinteger · int32

          What an ordering page quotes for collection, in minutes. A location setting.

          ≥ 0 · default 0

        • overtime_threshold_hoursinteger · int32

          Hours a member may work in a week here before the rota warns. 0 is no threshold. Absent from a write leaves it as it is.

          0–168

        • phone_numberstring

          Contact number in E.164 format.

          ≤ 32 chars

        • profilestring · enum

          Nullable

          What this location trades as, so the till and the back office show or default what that trade uses. Absent means show everything, the current behaviour. Presentation and defaults only, never enforcement.

          hospitalityretail

        • return_window_daysinteger · int32

          Nullable

          This location's own returns window, in days (retail item 10). Absent means the merchant's window applies — a merchant whose sites differ sets it here, where the customer is told it. Zero is a deliberate no-window at this site.

          ≥ 0

        • service_chargeServiceCharge

          Nullable

          This location's discretionary service charge, added to the bill before anyone pays (order-ledger item 9). null means the location charges none.

          • amountMoney

            Nullable

            The charge as a fixed amount per bill. Exactly one of percentage and amount is set.

            • amountinteger · int64

              Required

              The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

            • currencyCurrency

              Required

              ISO 4217 currency code.

              Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

              One of 182 values; see the schema.

          • discretionaryboolean

            Required

            Whether the guest may decline the charge. A charge that cannot be declined is a mandatory one and is taxed as such.

            default true

          • eat_in_onlyboolean

            Required

            Whether the charge applies to on-premises (eat-in) fulfilments only, or to every fulfilment.

            default false

          • percentagePercentage

            A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

            A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

            pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

          • tax_class_idstring · uuid

            Nullable

            The tax class this location's service charge is taxed under (decision record 0054), resolved by the same dated rules as goods and keyed by fulfilment type and date. A market's pack sets it to the outside-scope/zero class for a discretionary charge and the standard class for a mandatory one. Null means the charge is not taxed.

        • service_periodsarray of ServicePeriod

          The named services in a day, such as lunch and dinner, each with its own turn times and pacing. Absent from a write leaves them as they are.

          ≤ 20 items

          • namestring

            Required

            1–64 chars

          • daysarray of integer

            The weekdays it runs, 1 (Monday) to 7 (Sunday). Empty or absent is every day.

            ≤ 7 items

          • end_minuteinteger

            Required

            0–1440

          • pacing_coversinteger · int32

            The most covers that may arrive in one slot during this service. 0 is no cap.

            ≥ 0

          • start_minuteinteger

            Required

            0–1439

          • turn_timesarray of TurnTime

            How long a party stays during this service. Empty uses the location's.

            ≤ 20 items

            • max_party_sizeinteger · int32

              Required

              1–100

            • minutesinteger · int32

              Required

              1–1440

        • statusstring · enum

          Required

          activeinactive

        • tax_registration_numberstring

          This venue's own tax registration (a VAT number, say), as a receipt that prints this address carries it. Absent, the merchant's number applies — right for a single-country merchant and a franchise, wrong for a multi-country estate, where the taxpayer is per country and the merchant's number must not print above a foreign address (receipts-and-printing item 21).

          ≤ 32 chars

        • timezoneTimezone

          Required

          IANA time zone identifier.

          Used to resolve a location's business day for reporting and settlement.

          One of 348 values; see the schema.

        • tip_policystring · enum

          Whether this location's terminal prompts the guest for a tip, and what it offers. The till sends it with a card checkout so the terminal offers a tip, and the tip the guest adds lands on the payment. off takes the amount with no prompt; allow lets the guest add one on the terminal, using the options configured there.

          offallow

          default off

        • tip_presetsarray of Percentage

          What a card checkout at this location offers when it prompts for a tip, lowest first and none preselected: the till's tender sheet and a guest paying from their own phone both offer exactly these, and the charge applies the tapped one without rounding anywhere else. ["18", "20", "25"] is the platform default, which is what a location opens with; the merchant may change it like any other location setting.

          ≥ 1 items · ≤ 4 items · default [18 20 25]

        • turn_timesarray of TurnTime

          How long a party holds its table, by size: each entry covers parties up to its max_party_size, in order. Absent from a write leaves them as they are.

          ≤ 20 items

          • max_party_sizeinteger · int32

            Required

            1–100

          • minutesinteger · int32

            Required

            1–1440

        • updated_atTimestamp

          RequiredRead only

          Server-assigned RFC 3339 timestamp, always UTC.

          Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

        • versionVersion

          RequiredRead only

          Optimistic concurrency version, raised by the server on every write. A version is never lower than one already returned for the resource, though it may rise by more than one.

          Returned in the ETag response header as well as in the body. Send it back in If-Match on an update and the write is rejected with 412 if anyone else has written since — which is what stops two tills silently overwriting each other's edit to the same product when both come back online at once.

          ≥ 1

      • next_cursorstring

        Nullable

        Opaque cursor for the next page, or null on the last page. Pass it back verbatim as the cursor query parameter; its contents are not part of this contract.

    • 400

      The request could not be parsed. Malformed JSON, a bad query parameter, or a header that failed to decode, among them an API-Version later than the server speaks or not a date (api-version-unknown, with the server's own in api_version).

      Distinct from 422: a 400 never reached validation, so invalid_params is absent. Retrying without changing the request will fail again, except that a request refused for its API-Version goes once the server is updated.

    • 401

      No credentials, or credentials that could not be verified — missing bearer token, malformed JWT, expired token, or a signature that failed against the issuer's JWKS.

      Refresh the token and retry once. Repeated 401 after a refresh means the device needs to re-enrol.

    • 403

      Authenticated, but not permitted. The token is valid and its merchant was resolved, but the caller's role does not allow this operation, or the target belongs to a different merchant.

      Cross-tenant access is reported as 403 on a resource the caller may not see, and as 404 where even confirming existence would leak information. Retrying will not help.

    • 410

      The request names an API-Version this server no longer serves (docs/decisions/0011). Nothing in it was read. api_version names the version the server speaks: the client is behind, and sends the request again once it is updated.

    • 422

      The request parsed but failed validation.

      invalid_params lists every failing field with a JSON Pointer, not just the first, so a client can mark up a whole form in one pass rather than making the user fix errors one round trip at a time.

      Also returned when an Idempotency-Key is replayed with a different body, and when device-computed order totals disagree with the server's recomputation.

    • 429

      Rate limit exceeded. Honour Retry-After rather than applying your own backoff.

      A fleet of tills coming back online together after an outage is the realistic cause, which is exactly when uncoordinated client-side retry turns a brief outage into a sustained one. The limit is per process, and per site for what records trade there — a request spends its site's budget, and a till's own smaller one inside it — and per (client, merchant) for everything else; no RateLimit field is sent, so this response and its Retry-After are the whole of the contract.

    • 500

      Something failed on our side. trace_id identifies the request in our tracing — quote it in a support ticket.

      The body never carries internal detail: no SQL, no stack traces, no upstream error strings. Safe to retry with the same Idempotency-Key.

    • 503

      Temporarily unable to serve the request — a dependency is down or the service is shedding load.

      Retry with the same Idempotency-Key after Retry-After. This is always safe: a request that did take effect before the failure will be recognised as a replay.

  4. POST/v1/locations

    Create a location

    No. createLocationAuth bearer

    Adds a location — a shop, stall or van.

    Parameters

    • Idempotency-Keyheader · string

      Required

      A client-generated key making this request safe to retry.

      Required on every mutation that creates a resource or moves money. A till on bad wifi cannot tell a lost response from a lost request; without a key its only options are to risk a duplicate sale or to drop a real one. With a key it retries freely: the first request to arrive is processed, and every replay returns that same stored response.

      Rules:

      • Mint the key once, when the operation is first queued, and reuse it for every retry. A fresh key per attempt defeats the mechanism entirely.
      • Keys are scoped per merchant and per operation, and are retained for 30 days — long enough that a till switched off mid-sync can retry with the same key however long it stayed on the shelf.
      • Replaying a key with a different request body is a client bug and is rejected with 422, rather than silently returning the first result — quietly serving the old response would hide a real inconsistency in the caller.

      A UUIDv7 or ULID is a good choice.

    Request body application/json · Location

    • idstring · uuid

      Required

      UUIDv7 identifying the location.

    • typestring · enum

      Required

      mobile locations — market stalls, food vans — are expected to spend meaningful time offline, and are the reason the sync contract exists.

      physicalmobile

    • namestring

      Required

      Human-readable name, unique within the merchant. Appears in the dashboard and on receipts.

      1–255 chars

    • addressAddress

      A postal address.

      The address_line_* fields carry the most specific part of the address — street number, street name, building name. Less specific detail belongs in locality, administrative_district_level_* and country.

      The administrative_district_level_* fields are deliberately generic because their meaning is country-dependent: in the US level 1 is the state and level 2 the county; in the UK level 1 is the county.

      • address_line_1string

        Required

        First line of the address — street number, street name, building name.

        ≤ 255 chars

      • address_line_2string

        Second line of the address, if any.

        ≤ 255 chars

      • address_line_3string

        Third line of the address, if any.

        ≤ 255 chars

      • administrative_district_level_1string

        A civil entity within the country. The state in the US; the county in the UK.

        ≤ 128 chars

      • administrative_district_level_2string

        A civil entity within administrative_district_level_1.

        ≤ 128 chars

      • countryCountry

        Required

        ISO 3166-1 alpha-2 country code.

        ZZ is the unknown/unspecified placeholder.

        One of 250 values; see the schema.

      • localitystring

        The city or town.

        ≤ 128 chars

      • postal_codestring

        The postal or ZIP code.

        ≤ 32 chars

      • sublocalitystring

        A civil region within the locality, if any.

        ≤ 128 chars

    • auto_close_default_tip_percentagePercentage

      A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

      A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

      pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

    • auto_close_enabledboolean

      On, when this location's day closes, every open tab holding a card is settled with auto_close_default_tip_percentage; a tab with no card is left open and flagged left-overnight (tabs item 9).

    • booking_hoursarray of DaypartWindow

      The hours this location takes bookings, in its own timezone. Empty takes none. Absent from a write leaves them as they are.

      ≤ 28 items

      • daysarray of integer

        The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

        ≤ 7 items

      • end_minuteinteger

        Required

        1–1440

      • start_minuteinteger

        Required

        0–1439

    • break_threshold_minutesinteger · int32

      How long a shift at this location may run before a break is expected, in minutes. Zero disables the rule. Replaces the hard-coded six hours in the timesheet.

      ≥ 0 · default 360

    • business_day_start_local_timestring

      When this location's trading day begins, as a wall-clock time in its timezone (RFC 3339 partial-time, in the shape Square uses for start_local_time). A sale before it belongs to the previous business day, so a bar's 00:30 round counts towards last night's takings rather than today's.

      Defaults to 04:00, as Toast's closeout hour does: nothing that opens before four in the morning is affected, and every late-night venue is. Changing it affects sales from then on; days already traded keep the business date they were given.

      pattern ^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$ · default 04:00:00

    • business_emailstring · email

      The address a guest's reply to an email this venue sent should reach: the Reply-To on the guest messages this location's emails send. Empty means a reply goes to the platform, which answers for the venue.

      ≤ 254 chars

    • business_hoursarray of DaypartWindow

      The hours this location trades, in its own timezone, which the marketplace shows as open or closed. Apart from booking_hours. Absent from a write leaves them as they are.

      ≤ 8 items

      • daysarray of integer

        The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

        ≤ 7 items

      • end_minuteinteger

        Required

        1–1440

      • start_minuteinteger

        Required

        0–1439

    • cash_stepMoney

      A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

      The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

      Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

      • amountinteger · int64

        Required

        The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

      • currencyCurrency

        Required

        ISO 4217 currency code.

        Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

        One of 182 values; see the schema.

    • coordinatesCoordinates

      Nullable

      Where the location is, placed by the merchant, which the marketplace sorts guests' results by. null until placed. Absent from a write leaves it as it is.

      • latitudenumber · double

        Required

        -90–90

      • longitudenumber · double

        Required

        -180–180

    • currencyCurrency

      Required

      ISO 4217 currency code.

      Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

      One of 182 values; see the schema.

    • descriptionstring

      What the location says about itself on the marketplace. Absent from a write leaves it as it is.

      ≤ 280 chars

    • favoritesarray of string · uuid

      A shop's favourites, Square's Favorites and Toast's speed menu: up to twenty-four of its products, in this order, which a till in retail shows first, before the catalogue. Empty means the catalogue alone. Chosen in the back office; a device never writes it.

      ≤ 24 items · default []

    • kds_amber_minutesinteger · int32

      How long a kitchen ticket may wait (in minutes) before a kitchen display colours it amber. A location setting; the till paints from it.

      ≥ 1 · default 10

    • kds_red_minutesinteger · int32

      How long a kitchen ticket may wait (in minutes) before a kitchen display colours it red. A location setting; the till paints from it.

      ≥ 1 · default 20

    • labor_budgetMoney

      Nullable

      What a week's labor here is planned to cost, which the rota compares against. null sets none. Absent from a write leaves it as it is.

      • amountinteger · int64

        Required

        The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

      • currencyCurrency

        Required

        ISO 4217 currency code.

        Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

        One of 182 values; see the schema.

    • labor_target_percentagePercentage

      Nullable

      What labor here should cost as a share of net sales, which Home and the labor report set the day's cost against. null sets none. Absent from a write leaves it as it is.

      pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

    • language_codeLanguageCode

      IETF BCP 47 language tag.

      Used for receipts, dashboard copy and buyer-facing text.

      One of 30 values; see the schema.

    • min_break_minutesinteger · int32

      The least a break that is taken should be, in minutes. A shift with a break shorter than this still counts as missed.

      ≥ 0 · default 0

    • online_bookingOnlineBooking

      Whether guests may book this location themselves on its booking page, how far ahead and for how many, and how much of the room is kept for walk-ins. Absent from a write leaves it as it is.

      • days_aheadinteger · int32

        Required

        0–365

      • deposit_per_personMoney

        A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

        The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

        Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • enabledboolean

        Required

      • max_party_sizeinteger · int32

        Required

        The largest party a guest may book online. 0 is no limit.

        0–100

      • waitlist_enabledboolean

        Whether guests may join this location's waitlist from its own page. Distinct from enabled: a venue may take bookings online and not queue walk-ins from the web, or queue them and take no bookings. Absent from a write leaves it as it is.

      • walk_in_percentagePercentage

        Required

        A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

        A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

    • ordering_pausedboolean

      When true, a channel's new open orders are refused — the kitchen could not take another one. The till keeps selling regardless, and the setting is carried on the change feed so every surface hears it without a poll.

      default false

    • ordering_prep_time_minutesinteger · int32

      What an ordering page quotes for collection, in minutes. A location setting.

      ≥ 0 · default 0

    • overtime_threshold_hoursinteger · int32

      Hours a member may work in a week here before the rota warns. 0 is no threshold. Absent from a write leaves it as it is.

      0–168

    • phone_numberstring

      Contact number in E.164 format.

      ≤ 32 chars

    • profilestring · enum

      Nullable

      What this location trades as, so the till and the back office show or default what that trade uses. Absent means show everything, the current behaviour. Presentation and defaults only, never enforcement.

      hospitalityretail

    • return_window_daysinteger · int32

      Nullable

      This location's own returns window, in days (retail item 10). Absent means the merchant's window applies — a merchant whose sites differ sets it here, where the customer is told it. Zero is a deliberate no-window at this site.

      ≥ 0

    • service_chargeServiceCharge

      Nullable

      This location's discretionary service charge, added to the bill before anyone pays (order-ledger item 9). null means the location charges none.

      • amountMoney

        Nullable

        The charge as a fixed amount per bill. Exactly one of percentage and amount is set.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • discretionaryboolean

        Required

        Whether the guest may decline the charge. A charge that cannot be declined is a mandatory one and is taxed as such.

        default true

      • eat_in_onlyboolean

        Required

        Whether the charge applies to on-premises (eat-in) fulfilments only, or to every fulfilment.

        default false

      • percentagePercentage

        A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

        A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • tax_class_idstring · uuid

        Nullable

        The tax class this location's service charge is taxed under (decision record 0054), resolved by the same dated rules as goods and keyed by fulfilment type and date. A market's pack sets it to the outside-scope/zero class for a discretionary charge and the standard class for a mandatory one. Null means the charge is not taxed.

    • service_periodsarray of ServicePeriod

      The named services in a day, such as lunch and dinner, each with its own turn times and pacing. Absent from a write leaves them as they are.

      ≤ 20 items

      • namestring

        Required

        1–64 chars

      • daysarray of integer

        The weekdays it runs, 1 (Monday) to 7 (Sunday). Empty or absent is every day.

        ≤ 7 items

      • end_minuteinteger

        Required

        0–1440

      • pacing_coversinteger · int32

        The most covers that may arrive in one slot during this service. 0 is no cap.

        ≥ 0

      • start_minuteinteger

        Required

        0–1439

      • turn_timesarray of TurnTime

        How long a party stays during this service. Empty uses the location's.

        ≤ 20 items

        • max_party_sizeinteger · int32

          Required

          1–100

        • minutesinteger · int32

          Required

          1–1440

    • statusstring · enum

      Required

      activeinactive

    • tax_registration_numberstring

      This venue's own tax registration (a VAT number, say), as a receipt that prints this address carries it. Absent, the merchant's number applies — right for a single-country merchant and a franchise, wrong for a multi-country estate, where the taxpayer is per country and the merchant's number must not print above a foreign address (receipts-and-printing item 21).

      ≤ 32 chars

    • timezoneTimezone

      Required

      IANA time zone identifier.

      Used to resolve a location's business day for reporting and settlement.

      One of 348 values; see the schema.

    • tip_policystring · enum

      Whether this location's terminal prompts the guest for a tip, and what it offers. The till sends it with a card checkout so the terminal offers a tip, and the tip the guest adds lands on the payment. off takes the amount with no prompt; allow lets the guest add one on the terminal, using the options configured there.

      offallow

      default off

    • tip_presetsarray of Percentage

      What a card checkout at this location offers when it prompts for a tip, lowest first and none preselected: the till's tender sheet and a guest paying from their own phone both offer exactly these, and the charge applies the tapped one without rounding anywhere else. ["18", "20", "25"] is the platform default, which is what a location opens with; the merchant may change it like any other location setting.

      ≥ 1 items · ≤ 4 items · default [18 20 25]

    • turn_timesarray of TurnTime

      How long a party holds its table, by size: each entry covers parties up to its max_party_size, in order. Absent from a write leaves them as they are.

      ≤ 20 items

      • max_party_sizeinteger · int32

        Required

        1–100

      • minutesinteger · int32

        Required

        1–1440

    Responses

    • 201

      The location was created.

      Location · application/json
      • idstring · uuid

        Required

        UUIDv7 identifying the location.

      • typestring · enum

        Required

        mobile locations — market stalls, food vans — are expected to spend meaningful time offline, and are the reason the sync contract exists.

        physicalmobile

      • namestring

        Required

        Human-readable name, unique within the merchant. Appears in the dashboard and on receipts.

        1–255 chars

      • addressAddress

        A postal address.

        The address_line_* fields carry the most specific part of the address — street number, street name, building name. Less specific detail belongs in locality, administrative_district_level_* and country.

        The administrative_district_level_* fields are deliberately generic because their meaning is country-dependent: in the US level 1 is the state and level 2 the county; in the UK level 1 is the county.

        • address_line_1string

          Required

          First line of the address — street number, street name, building name.

          ≤ 255 chars

        • address_line_2string

          Second line of the address, if any.

          ≤ 255 chars

        • address_line_3string

          Third line of the address, if any.

          ≤ 255 chars

        • administrative_district_level_1string

          A civil entity within the country. The state in the US; the county in the UK.

          ≤ 128 chars

        • administrative_district_level_2string

          A civil entity within administrative_district_level_1.

          ≤ 128 chars

        • countryCountry

          Required

          ISO 3166-1 alpha-2 country code.

          ZZ is the unknown/unspecified placeholder.

          One of 250 values; see the schema.

        • localitystring

          The city or town.

          ≤ 128 chars

        • postal_codestring

          The postal or ZIP code.

          ≤ 32 chars

        • sublocalitystring

          A civil region within the locality, if any.

          ≤ 128 chars

      • auto_close_default_tip_percentagePercentage

        A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

        A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • auto_close_enabledboolean

        On, when this location's day closes, every open tab holding a card is settled with auto_close_default_tip_percentage; a tab with no card is left open and flagged left-overnight (tabs item 9).

      • booking_hoursarray of DaypartWindow

        The hours this location takes bookings, in its own timezone. Empty takes none. Absent from a write leaves them as they are.

        ≤ 28 items

        • daysarray of integer

          The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          1–1440

        • start_minuteinteger

          Required

          0–1439

      • break_threshold_minutesinteger · int32

        How long a shift at this location may run before a break is expected, in minutes. Zero disables the rule. Replaces the hard-coded six hours in the timesheet.

        ≥ 0 · default 360

      • business_day_start_local_timestring

        When this location's trading day begins, as a wall-clock time in its timezone (RFC 3339 partial-time, in the shape Square uses for start_local_time). A sale before it belongs to the previous business day, so a bar's 00:30 round counts towards last night's takings rather than today's.

        Defaults to 04:00, as Toast's closeout hour does: nothing that opens before four in the morning is affected, and every late-night venue is. Changing it affects sales from then on; days already traded keep the business date they were given.

        pattern ^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$ · default 04:00:00

      • business_emailstring · email

        The address a guest's reply to an email this venue sent should reach: the Reply-To on the guest messages this location's emails send. Empty means a reply goes to the platform, which answers for the venue.

        ≤ 254 chars

      • business_hoursarray of DaypartWindow

        The hours this location trades, in its own timezone, which the marketplace shows as open or closed. Apart from booking_hours. Absent from a write leaves them as they are.

        ≤ 8 items

        • daysarray of integer

          The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          1–1440

        • start_minuteinteger

          Required

          0–1439

      • cash_stepMoney

        A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

        The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

        Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • coordinatesCoordinates

        Nullable

        Where the location is, placed by the merchant, which the marketplace sorts guests' results by. null until placed. Absent from a write leaves it as it is.

        • latitudenumber · double

          Required

          -90–90

        • longitudenumber · double

          Required

          -180–180

      • created_atTimestamp

        RequiredRead only

        Server-assigned RFC 3339 timestamp, always UTC.

        Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

      • currencyCurrency

        Required

        ISO 4217 currency code.

        Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

        One of 182 values; see the schema.

      • descriptionstring

        What the location says about itself on the marketplace. Absent from a write leaves it as it is.

        ≤ 280 chars

      • favoritesarray of string · uuid

        A shop's favourites, Square's Favorites and Toast's speed menu: up to twenty-four of its products, in this order, which a till in retail shows first, before the catalogue. Empty means the catalogue alone. Chosen in the back office; a device never writes it.

        ≤ 24 items · default []

      • kds_amber_minutesinteger · int32

        How long a kitchen ticket may wait (in minutes) before a kitchen display colours it amber. A location setting; the till paints from it.

        ≥ 1 · default 10

      • kds_red_minutesinteger · int32

        How long a kitchen ticket may wait (in minutes) before a kitchen display colours it red. A location setting; the till paints from it.

        ≥ 1 · default 20

      • labor_budgetMoney

        Nullable

        What a week's labor here is planned to cost, which the rota compares against. null sets none. Absent from a write leaves it as it is.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • labor_target_percentagePercentage

        Nullable

        What labor here should cost as a share of net sales, which Home and the labor report set the day's cost against. null sets none. Absent from a write leaves it as it is.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • language_codeLanguageCode

        IETF BCP 47 language tag.

        Used for receipts, dashboard copy and buyer-facing text.

        One of 30 values; see the schema.

      • merchant_idstring · uuid

        RequiredRead only

        The owning merchant. Read-only and derived from the caller's token — a location can never be moved between merchants.

      • min_break_minutesinteger · int32

        The least a break that is taken should be, in minutes. A shift with a break shorter than this still counts as missed.

        ≥ 0 · default 0

      • online_bookingOnlineBooking

        Whether guests may book this location themselves on its booking page, how far ahead and for how many, and how much of the room is kept for walk-ins. Absent from a write leaves it as it is.

        • days_aheadinteger · int32

          Required

          0–365

        • deposit_per_personMoney

          A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

          The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

          Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • enabledboolean

          Required

        • max_party_sizeinteger · int32

          Required

          The largest party a guest may book online. 0 is no limit.

          0–100

        • waitlist_enabledboolean

          Whether guests may join this location's waitlist from its own page. Distinct from enabled: a venue may take bookings online and not queue walk-ins from the web, or queue them and take no bookings. Absent from a write leaves it as it is.

        • walk_in_percentagePercentage

          Required

          A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

          A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • ordering_auto_acceptboolean

        Read only

        Whether an order from the ordering page is accepted as it arrives, rather than waiting for somebody to take it on. Changed on the ordering settings, not by writing the location.

        default false

      • ordering_enabledboolean

        Read only

        Whether guests can order from this location's ordering page. Changed on the ordering settings, not by writing the location.

        default false

      • ordering_handlestring

        Read only

        The ordering page's name: its subdomain on the guest ordering site. Absent until one is chosen. Changed on the ordering settings, not by writing the location.

        ≤ 63 chars

      • ordering_pausedboolean

        When true, a channel's new open orders are refused — the kitchen could not take another one. The till keeps selling regardless, and the setting is carried on the change feed so every surface hears it without a poll.

        default false

      • ordering_prep_time_minutesinteger · int32

        What an ordering page quotes for collection, in minutes. A location setting.

        ≥ 0 · default 0

      • overtime_threshold_hoursinteger · int32

        Hours a member may work in a week here before the rota warns. 0 is no threshold. Absent from a write leaves it as it is.

        0–168

      • phone_numberstring

        Contact number in E.164 format.

        ≤ 32 chars

      • profilestring · enum

        Nullable

        What this location trades as, so the till and the back office show or default what that trade uses. Absent means show everything, the current behaviour. Presentation and defaults only, never enforcement.

        hospitalityretail

      • return_window_daysinteger · int32

        Nullable

        This location's own returns window, in days (retail item 10). Absent means the merchant's window applies — a merchant whose sites differ sets it here, where the customer is told it. Zero is a deliberate no-window at this site.

        ≥ 0

      • service_chargeServiceCharge

        Nullable

        This location's discretionary service charge, added to the bill before anyone pays (order-ledger item 9). null means the location charges none.

        • amountMoney

          Nullable

          The charge as a fixed amount per bill. Exactly one of percentage and amount is set.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • discretionaryboolean

          Required

          Whether the guest may decline the charge. A charge that cannot be declined is a mandatory one and is taxed as such.

          default true

        • eat_in_onlyboolean

          Required

          Whether the charge applies to on-premises (eat-in) fulfilments only, or to every fulfilment.

          default false

        • percentagePercentage

          A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

          A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

        • tax_class_idstring · uuid

          Nullable

          The tax class this location's service charge is taxed under (decision record 0054), resolved by the same dated rules as goods and keyed by fulfilment type and date. A market's pack sets it to the outside-scope/zero class for a discretionary charge and the standard class for a mandatory one. Null means the charge is not taxed.

      • service_periodsarray of ServicePeriod

        The named services in a day, such as lunch and dinner, each with its own turn times and pacing. Absent from a write leaves them as they are.

        ≤ 20 items

        • namestring

          Required

          1–64 chars

        • daysarray of integer

          The weekdays it runs, 1 (Monday) to 7 (Sunday). Empty or absent is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          0–1440

        • pacing_coversinteger · int32

          The most covers that may arrive in one slot during this service. 0 is no cap.

          ≥ 0

        • start_minuteinteger

          Required

          0–1439

        • turn_timesarray of TurnTime

          How long a party stays during this service. Empty uses the location's.

          ≤ 20 items

          • max_party_sizeinteger · int32

            Required

            1–100

          • minutesinteger · int32

            Required

            1–1440

      • statusstring · enum

        Required

        activeinactive

      • tax_registration_numberstring

        This venue's own tax registration (a VAT number, say), as a receipt that prints this address carries it. Absent, the merchant's number applies — right for a single-country merchant and a franchise, wrong for a multi-country estate, where the taxpayer is per country and the merchant's number must not print above a foreign address (receipts-and-printing item 21).

        ≤ 32 chars

      • timezoneTimezone

        Required

        IANA time zone identifier.

        Used to resolve a location's business day for reporting and settlement.

        One of 348 values; see the schema.

      • tip_policystring · enum

        Whether this location's terminal prompts the guest for a tip, and what it offers. The till sends it with a card checkout so the terminal offers a tip, and the tip the guest adds lands on the payment. off takes the amount with no prompt; allow lets the guest add one on the terminal, using the options configured there.

        offallow

        default off

      • tip_presetsarray of Percentage

        What a card checkout at this location offers when it prompts for a tip, lowest first and none preselected: the till's tender sheet and a guest paying from their own phone both offer exactly these, and the charge applies the tapped one without rounding anywhere else. ["18", "20", "25"] is the platform default, which is what a location opens with; the merchant may change it like any other location setting.

        ≥ 1 items · ≤ 4 items · default [18 20 25]

      • turn_timesarray of TurnTime

        How long a party holds its table, by size: each entry covers parties up to its max_party_size, in order. Absent from a write leaves them as they are.

        ≤ 20 items

        • max_party_sizeinteger · int32

          Required

          1–100

        • minutesinteger · int32

          Required

          1–1440

      • updated_atTimestamp

        RequiredRead only

        Server-assigned RFC 3339 timestamp, always UTC.

        Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

      • versionVersion

        RequiredRead only

        Optimistic concurrency version, raised by the server on every write. A version is never lower than one already returned for the resource, though it may rise by more than one.

        Returned in the ETag response header as well as in the body. Send it back in If-Match on an update and the write is rejected with 412 if anyone else has written since — which is what stops two tills silently overwriting each other's edit to the same product when both come back online at once.

        ≥ 1

    • 400

      The request could not be parsed. Malformed JSON, a bad query parameter, or a header that failed to decode, among them an API-Version later than the server speaks or not a date (api-version-unknown, with the server's own in api_version).

      Distinct from 422: a 400 never reached validation, so invalid_params is absent. Retrying without changing the request will fail again, except that a request refused for its API-Version goes once the server is updated.

    • 401

      No credentials, or credentials that could not be verified — missing bearer token, malformed JWT, expired token, or a signature that failed against the issuer's JWKS.

      Refresh the token and retry once. Repeated 401 after a refresh means the device needs to re-enrol.

    • 403

      Authenticated, but not permitted. The token is valid and its merchant was resolved, but the caller's role does not allow this operation, or the target belongs to a different merchant.

      Cross-tenant access is reported as 403 on a resource the caller may not see, and as 404 where even confirming existence would leak information. Retrying will not help.

    • 409

      The request conflicts with current state — a uniqueness constraint, or an attempt to mutate an order that is already completed or voided.

      Unlike 412, re-reading and retrying unchanged will not resolve it; the request itself has to change.

    • 410

      The request names an API-Version this server no longer serves (docs/decisions/0011). Nothing in it was read. api_version names the version the server speaks: the client is behind, and sends the request again once it is updated.

    • 415

      The request Content-Type is not supported. This API accepts application/json on all mutations.

    • 422

      The request parsed but failed validation.

      invalid_params lists every failing field with a JSON Pointer, not just the first, so a client can mark up a whole form in one pass rather than making the user fix errors one round trip at a time.

      Also returned when an Idempotency-Key is replayed with a different body, and when device-computed order totals disagree with the server's recomputation.

    • 429

      Rate limit exceeded. Honour Retry-After rather than applying your own backoff.

      A fleet of tills coming back online together after an outage is the realistic cause, which is exactly when uncoordinated client-side retry turns a brief outage into a sustained one. The limit is per process, and per site for what records trade there — a request spends its site's budget, and a till's own smaller one inside it — and per (client, merchant) for everything else; no RateLimit field is sent, so this response and its Retry-After are the whole of the contract.

    • 500

      Something failed on our side. trace_id identifies the request in our tracing — quote it in a support ticket.

      The body never carries internal detail: no SQL, no stack traces, no upstream error strings. Safe to retry with the same Idempotency-Key.

    • 503

      Temporarily unable to serve the request — a dependency is down or the service is shedding load.

      Retry with the same Idempotency-Key after Retry-After. This is always safe: a request that did take effect before the failure will be recognised as a replay.

  5. GET/v1/locations/{id}

    Get a location

    No. getLocationAuth bearer

    Returns a single location.

    Parameters

    • idpath · string · uuid

      Required

      UUIDv7 of the resource.

      For resources a device can originate — orders, and their line items — this id is minted by the client before the record is ever synced, which is what makes an offline create idempotent.

    Responses

    • 200

      The location.

      Location · application/json
      • idstring · uuid

        Required

        UUIDv7 identifying the location.

      • typestring · enum

        Required

        mobile locations — market stalls, food vans — are expected to spend meaningful time offline, and are the reason the sync contract exists.

        physicalmobile

      • namestring

        Required

        Human-readable name, unique within the merchant. Appears in the dashboard and on receipts.

        1–255 chars

      • addressAddress

        A postal address.

        The address_line_* fields carry the most specific part of the address — street number, street name, building name. Less specific detail belongs in locality, administrative_district_level_* and country.

        The administrative_district_level_* fields are deliberately generic because their meaning is country-dependent: in the US level 1 is the state and level 2 the county; in the UK level 1 is the county.

        • address_line_1string

          Required

          First line of the address — street number, street name, building name.

          ≤ 255 chars

        • address_line_2string

          Second line of the address, if any.

          ≤ 255 chars

        • address_line_3string

          Third line of the address, if any.

          ≤ 255 chars

        • administrative_district_level_1string

          A civil entity within the country. The state in the US; the county in the UK.

          ≤ 128 chars

        • administrative_district_level_2string

          A civil entity within administrative_district_level_1.

          ≤ 128 chars

        • countryCountry

          Required

          ISO 3166-1 alpha-2 country code.

          ZZ is the unknown/unspecified placeholder.

          One of 250 values; see the schema.

        • localitystring

          The city or town.

          ≤ 128 chars

        • postal_codestring

          The postal or ZIP code.

          ≤ 32 chars

        • sublocalitystring

          A civil region within the locality, if any.

          ≤ 128 chars

      • auto_close_default_tip_percentagePercentage

        A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

        A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • auto_close_enabledboolean

        On, when this location's day closes, every open tab holding a card is settled with auto_close_default_tip_percentage; a tab with no card is left open and flagged left-overnight (tabs item 9).

      • booking_hoursarray of DaypartWindow

        The hours this location takes bookings, in its own timezone. Empty takes none. Absent from a write leaves them as they are.

        ≤ 28 items

        • daysarray of integer

          The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          1–1440

        • start_minuteinteger

          Required

          0–1439

      • break_threshold_minutesinteger · int32

        How long a shift at this location may run before a break is expected, in minutes. Zero disables the rule. Replaces the hard-coded six hours in the timesheet.

        ≥ 0 · default 360

      • business_day_start_local_timestring

        When this location's trading day begins, as a wall-clock time in its timezone (RFC 3339 partial-time, in the shape Square uses for start_local_time). A sale before it belongs to the previous business day, so a bar's 00:30 round counts towards last night's takings rather than today's.

        Defaults to 04:00, as Toast's closeout hour does: nothing that opens before four in the morning is affected, and every late-night venue is. Changing it affects sales from then on; days already traded keep the business date they were given.

        pattern ^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$ · default 04:00:00

      • business_emailstring · email

        The address a guest's reply to an email this venue sent should reach: the Reply-To on the guest messages this location's emails send. Empty means a reply goes to the platform, which answers for the venue.

        ≤ 254 chars

      • business_hoursarray of DaypartWindow

        The hours this location trades, in its own timezone, which the marketplace shows as open or closed. Apart from booking_hours. Absent from a write leaves them as they are.

        ≤ 8 items

        • daysarray of integer

          The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          1–1440

        • start_minuteinteger

          Required

          0–1439

      • cash_stepMoney

        A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

        The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

        Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • coordinatesCoordinates

        Nullable

        Where the location is, placed by the merchant, which the marketplace sorts guests' results by. null until placed. Absent from a write leaves it as it is.

        • latitudenumber · double

          Required

          -90–90

        • longitudenumber · double

          Required

          -180–180

      • created_atTimestamp

        RequiredRead only

        Server-assigned RFC 3339 timestamp, always UTC.

        Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

      • currencyCurrency

        Required

        ISO 4217 currency code.

        Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

        One of 182 values; see the schema.

      • descriptionstring

        What the location says about itself on the marketplace. Absent from a write leaves it as it is.

        ≤ 280 chars

      • favoritesarray of string · uuid

        A shop's favourites, Square's Favorites and Toast's speed menu: up to twenty-four of its products, in this order, which a till in retail shows first, before the catalogue. Empty means the catalogue alone. Chosen in the back office; a device never writes it.

        ≤ 24 items · default []

      • kds_amber_minutesinteger · int32

        How long a kitchen ticket may wait (in minutes) before a kitchen display colours it amber. A location setting; the till paints from it.

        ≥ 1 · default 10

      • kds_red_minutesinteger · int32

        How long a kitchen ticket may wait (in minutes) before a kitchen display colours it red. A location setting; the till paints from it.

        ≥ 1 · default 20

      • labor_budgetMoney

        Nullable

        What a week's labor here is planned to cost, which the rota compares against. null sets none. Absent from a write leaves it as it is.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • labor_target_percentagePercentage

        Nullable

        What labor here should cost as a share of net sales, which Home and the labor report set the day's cost against. null sets none. Absent from a write leaves it as it is.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • language_codeLanguageCode

        IETF BCP 47 language tag.

        Used for receipts, dashboard copy and buyer-facing text.

        One of 30 values; see the schema.

      • merchant_idstring · uuid

        RequiredRead only

        The owning merchant. Read-only and derived from the caller's token — a location can never be moved between merchants.

      • min_break_minutesinteger · int32

        The least a break that is taken should be, in minutes. A shift with a break shorter than this still counts as missed.

        ≥ 0 · default 0

      • online_bookingOnlineBooking

        Whether guests may book this location themselves on its booking page, how far ahead and for how many, and how much of the room is kept for walk-ins. Absent from a write leaves it as it is.

        • days_aheadinteger · int32

          Required

          0–365

        • deposit_per_personMoney

          A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

          The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

          Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • enabledboolean

          Required

        • max_party_sizeinteger · int32

          Required

          The largest party a guest may book online. 0 is no limit.

          0–100

        • waitlist_enabledboolean

          Whether guests may join this location's waitlist from its own page. Distinct from enabled: a venue may take bookings online and not queue walk-ins from the web, or queue them and take no bookings. Absent from a write leaves it as it is.

        • walk_in_percentagePercentage

          Required

          A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

          A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • ordering_auto_acceptboolean

        Read only

        Whether an order from the ordering page is accepted as it arrives, rather than waiting for somebody to take it on. Changed on the ordering settings, not by writing the location.

        default false

      • ordering_enabledboolean

        Read only

        Whether guests can order from this location's ordering page. Changed on the ordering settings, not by writing the location.

        default false

      • ordering_handlestring

        Read only

        The ordering page's name: its subdomain on the guest ordering site. Absent until one is chosen. Changed on the ordering settings, not by writing the location.

        ≤ 63 chars

      • ordering_pausedboolean

        When true, a channel's new open orders are refused — the kitchen could not take another one. The till keeps selling regardless, and the setting is carried on the change feed so every surface hears it without a poll.

        default false

      • ordering_prep_time_minutesinteger · int32

        What an ordering page quotes for collection, in minutes. A location setting.

        ≥ 0 · default 0

      • overtime_threshold_hoursinteger · int32

        Hours a member may work in a week here before the rota warns. 0 is no threshold. Absent from a write leaves it as it is.

        0–168

      • phone_numberstring

        Contact number in E.164 format.

        ≤ 32 chars

      • profilestring · enum

        Nullable

        What this location trades as, so the till and the back office show or default what that trade uses. Absent means show everything, the current behaviour. Presentation and defaults only, never enforcement.

        hospitalityretail

      • return_window_daysinteger · int32

        Nullable

        This location's own returns window, in days (retail item 10). Absent means the merchant's window applies — a merchant whose sites differ sets it here, where the customer is told it. Zero is a deliberate no-window at this site.

        ≥ 0

      • service_chargeServiceCharge

        Nullable

        This location's discretionary service charge, added to the bill before anyone pays (order-ledger item 9). null means the location charges none.

        • amountMoney

          Nullable

          The charge as a fixed amount per bill. Exactly one of percentage and amount is set.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • discretionaryboolean

          Required

          Whether the guest may decline the charge. A charge that cannot be declined is a mandatory one and is taxed as such.

          default true

        • eat_in_onlyboolean

          Required

          Whether the charge applies to on-premises (eat-in) fulfilments only, or to every fulfilment.

          default false

        • percentagePercentage

          A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

          A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

        • tax_class_idstring · uuid

          Nullable

          The tax class this location's service charge is taxed under (decision record 0054), resolved by the same dated rules as goods and keyed by fulfilment type and date. A market's pack sets it to the outside-scope/zero class for a discretionary charge and the standard class for a mandatory one. Null means the charge is not taxed.

      • service_periodsarray of ServicePeriod

        The named services in a day, such as lunch and dinner, each with its own turn times and pacing. Absent from a write leaves them as they are.

        ≤ 20 items

        • namestring

          Required

          1–64 chars

        • daysarray of integer

          The weekdays it runs, 1 (Monday) to 7 (Sunday). Empty or absent is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          0–1440

        • pacing_coversinteger · int32

          The most covers that may arrive in one slot during this service. 0 is no cap.

          ≥ 0

        • start_minuteinteger

          Required

          0–1439

        • turn_timesarray of TurnTime

          How long a party stays during this service. Empty uses the location's.

          ≤ 20 items

          • max_party_sizeinteger · int32

            Required

            1–100

          • minutesinteger · int32

            Required

            1–1440

      • statusstring · enum

        Required

        activeinactive

      • tax_registration_numberstring

        This venue's own tax registration (a VAT number, say), as a receipt that prints this address carries it. Absent, the merchant's number applies — right for a single-country merchant and a franchise, wrong for a multi-country estate, where the taxpayer is per country and the merchant's number must not print above a foreign address (receipts-and-printing item 21).

        ≤ 32 chars

      • timezoneTimezone

        Required

        IANA time zone identifier.

        Used to resolve a location's business day for reporting and settlement.

        One of 348 values; see the schema.

      • tip_policystring · enum

        Whether this location's terminal prompts the guest for a tip, and what it offers. The till sends it with a card checkout so the terminal offers a tip, and the tip the guest adds lands on the payment. off takes the amount with no prompt; allow lets the guest add one on the terminal, using the options configured there.

        offallow

        default off

      • tip_presetsarray of Percentage

        What a card checkout at this location offers when it prompts for a tip, lowest first and none preselected: the till's tender sheet and a guest paying from their own phone both offer exactly these, and the charge applies the tapped one without rounding anywhere else. ["18", "20", "25"] is the platform default, which is what a location opens with; the merchant may change it like any other location setting.

        ≥ 1 items · ≤ 4 items · default [18 20 25]

      • turn_timesarray of TurnTime

        How long a party holds its table, by size: each entry covers parties up to its max_party_size, in order. Absent from a write leaves them as they are.

        ≤ 20 items

        • max_party_sizeinteger · int32

          Required

          1–100

        • minutesinteger · int32

          Required

          1–1440

      • updated_atTimestamp

        RequiredRead only

        Server-assigned RFC 3339 timestamp, always UTC.

        Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

      • versionVersion

        RequiredRead only

        Optimistic concurrency version, raised by the server on every write. A version is never lower than one already returned for the resource, though it may rise by more than one.

        Returned in the ETag response header as well as in the body. Send it back in If-Match on an update and the write is rejected with 412 if anyone else has written since — which is what stops two tills silently overwriting each other's edit to the same product when both come back online at once.

        ≥ 1

    • 400

      The request could not be parsed. Malformed JSON, a bad query parameter, or a header that failed to decode, among them an API-Version later than the server speaks or not a date (api-version-unknown, with the server's own in api_version).

      Distinct from 422: a 400 never reached validation, so invalid_params is absent. Retrying without changing the request will fail again, except that a request refused for its API-Version goes once the server is updated.

    • 401

      No credentials, or credentials that could not be verified — missing bearer token, malformed JWT, expired token, or a signature that failed against the issuer's JWKS.

      Refresh the token and retry once. Repeated 401 after a refresh means the device needs to re-enrol.

    • 403

      Authenticated, but not permitted. The token is valid and its merchant was resolved, but the caller's role does not allow this operation, or the target belongs to a different merchant.

      Cross-tenant access is reported as 403 on a resource the caller may not see, and as 404 where even confirming existence would leak information. Retrying will not help.

    • 404

      No such resource, or none visible to this caller.

      Also returned instead of 403 where acknowledging existence would itself leak information — so a 404 does not prove the id is unused globally, only that it is not yours.

    • 410

      The request names an API-Version this server no longer serves (docs/decisions/0011). Nothing in it was read. api_version names the version the server speaks: the client is behind, and sends the request again once it is updated.

    • 429

      Rate limit exceeded. Honour Retry-After rather than applying your own backoff.

      A fleet of tills coming back online together after an outage is the realistic cause, which is exactly when uncoordinated client-side retry turns a brief outage into a sustained one. The limit is per process, and per site for what records trade there — a request spends its site's budget, and a till's own smaller one inside it — and per (client, merchant) for everything else; no RateLimit field is sent, so this response and its Retry-After are the whole of the contract.

    • 500

      Something failed on our side. trace_id identifies the request in our tracing — quote it in a support ticket.

      The body never carries internal detail: no SQL, no stack traces, no upstream error strings. Safe to retry with the same Idempotency-Key.

    • 503

      Temporarily unable to serve the request — a dependency is down or the service is shedding load.

      Retry with the same Idempotency-Key after Retry-After. This is always safe: a request that did take effect before the failure will be recognised as a replay.

  6. PUT/v1/locations/{id}

    Update a location

    No. updateLocationAuth bearer

    Replaces a location, guarded by If-Match.

    Parameters

    • idpath · string · uuid

      Required

      UUIDv7 of the resource.

      For resources a device can originate — orders, and their line items — this id is minted by the client before the record is ever synced, which is what makes an offline create idempotent.

    • If-Matchheader · string

      Required

      The ETag from the read that produced the value you are updating.

      Required on updates, not optional, because "last write wins" is the wrong default for a catalogue two managers might edit at once. If anything has been written since your read, the request is rejected with 412 and you re-read and re-apply.

      Use * to mean "write regardless of current version" — an explicit, greppable override rather than the silent default.

    Request body application/json · Location

    • idstring · uuid

      Required

      UUIDv7 identifying the location.

    • typestring · enum

      Required

      mobile locations — market stalls, food vans — are expected to spend meaningful time offline, and are the reason the sync contract exists.

      physicalmobile

    • namestring

      Required

      Human-readable name, unique within the merchant. Appears in the dashboard and on receipts.

      1–255 chars

    • addressAddress

      A postal address.

      The address_line_* fields carry the most specific part of the address — street number, street name, building name. Less specific detail belongs in locality, administrative_district_level_* and country.

      The administrative_district_level_* fields are deliberately generic because their meaning is country-dependent: in the US level 1 is the state and level 2 the county; in the UK level 1 is the county.

      • address_line_1string

        Required

        First line of the address — street number, street name, building name.

        ≤ 255 chars

      • address_line_2string

        Second line of the address, if any.

        ≤ 255 chars

      • address_line_3string

        Third line of the address, if any.

        ≤ 255 chars

      • administrative_district_level_1string

        A civil entity within the country. The state in the US; the county in the UK.

        ≤ 128 chars

      • administrative_district_level_2string

        A civil entity within administrative_district_level_1.

        ≤ 128 chars

      • countryCountry

        Required

        ISO 3166-1 alpha-2 country code.

        ZZ is the unknown/unspecified placeholder.

        One of 250 values; see the schema.

      • localitystring

        The city or town.

        ≤ 128 chars

      • postal_codestring

        The postal or ZIP code.

        ≤ 32 chars

      • sublocalitystring

        A civil region within the locality, if any.

        ≤ 128 chars

    • auto_close_default_tip_percentagePercentage

      A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

      A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

      pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

    • auto_close_enabledboolean

      On, when this location's day closes, every open tab holding a card is settled with auto_close_default_tip_percentage; a tab with no card is left open and flagged left-overnight (tabs item 9).

    • booking_hoursarray of DaypartWindow

      The hours this location takes bookings, in its own timezone. Empty takes none. Absent from a write leaves them as they are.

      ≤ 28 items

      • daysarray of integer

        The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

        ≤ 7 items

      • end_minuteinteger

        Required

        1–1440

      • start_minuteinteger

        Required

        0–1439

    • break_threshold_minutesinteger · int32

      How long a shift at this location may run before a break is expected, in minutes. Zero disables the rule. Replaces the hard-coded six hours in the timesheet.

      ≥ 0 · default 360

    • business_day_start_local_timestring

      When this location's trading day begins, as a wall-clock time in its timezone (RFC 3339 partial-time, in the shape Square uses for start_local_time). A sale before it belongs to the previous business day, so a bar's 00:30 round counts towards last night's takings rather than today's.

      Defaults to 04:00, as Toast's closeout hour does: nothing that opens before four in the morning is affected, and every late-night venue is. Changing it affects sales from then on; days already traded keep the business date they were given.

      pattern ^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$ · default 04:00:00

    • business_emailstring · email

      The address a guest's reply to an email this venue sent should reach: the Reply-To on the guest messages this location's emails send. Empty means a reply goes to the platform, which answers for the venue.

      ≤ 254 chars

    • business_hoursarray of DaypartWindow

      The hours this location trades, in its own timezone, which the marketplace shows as open or closed. Apart from booking_hours. Absent from a write leaves them as they are.

      ≤ 8 items

      • daysarray of integer

        The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

        ≤ 7 items

      • end_minuteinteger

        Required

        1–1440

      • start_minuteinteger

        Required

        0–1439

    • cash_stepMoney

      A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

      The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

      Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

      • amountinteger · int64

        Required

        The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

      • currencyCurrency

        Required

        ISO 4217 currency code.

        Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

        One of 182 values; see the schema.

    • coordinatesCoordinates

      Nullable

      Where the location is, placed by the merchant, which the marketplace sorts guests' results by. null until placed. Absent from a write leaves it as it is.

      • latitudenumber · double

        Required

        -90–90

      • longitudenumber · double

        Required

        -180–180

    • currencyCurrency

      Required

      ISO 4217 currency code.

      Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

      One of 182 values; see the schema.

    • descriptionstring

      What the location says about itself on the marketplace. Absent from a write leaves it as it is.

      ≤ 280 chars

    • favoritesarray of string · uuid

      A shop's favourites, Square's Favorites and Toast's speed menu: up to twenty-four of its products, in this order, which a till in retail shows first, before the catalogue. Empty means the catalogue alone. Chosen in the back office; a device never writes it.

      ≤ 24 items · default []

    • kds_amber_minutesinteger · int32

      How long a kitchen ticket may wait (in minutes) before a kitchen display colours it amber. A location setting; the till paints from it.

      ≥ 1 · default 10

    • kds_red_minutesinteger · int32

      How long a kitchen ticket may wait (in minutes) before a kitchen display colours it red. A location setting; the till paints from it.

      ≥ 1 · default 20

    • labor_budgetMoney

      Nullable

      What a week's labor here is planned to cost, which the rota compares against. null sets none. Absent from a write leaves it as it is.

      • amountinteger · int64

        Required

        The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

      • currencyCurrency

        Required

        ISO 4217 currency code.

        Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

        One of 182 values; see the schema.

    • labor_target_percentagePercentage

      Nullable

      What labor here should cost as a share of net sales, which Home and the labor report set the day's cost against. null sets none. Absent from a write leaves it as it is.

      pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

    • language_codeLanguageCode

      IETF BCP 47 language tag.

      Used for receipts, dashboard copy and buyer-facing text.

      One of 30 values; see the schema.

    • min_break_minutesinteger · int32

      The least a break that is taken should be, in minutes. A shift with a break shorter than this still counts as missed.

      ≥ 0 · default 0

    • online_bookingOnlineBooking

      Whether guests may book this location themselves on its booking page, how far ahead and for how many, and how much of the room is kept for walk-ins. Absent from a write leaves it as it is.

      • days_aheadinteger · int32

        Required

        0–365

      • deposit_per_personMoney

        A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

        The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

        Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • enabledboolean

        Required

      • max_party_sizeinteger · int32

        Required

        The largest party a guest may book online. 0 is no limit.

        0–100

      • waitlist_enabledboolean

        Whether guests may join this location's waitlist from its own page. Distinct from enabled: a venue may take bookings online and not queue walk-ins from the web, or queue them and take no bookings. Absent from a write leaves it as it is.

      • walk_in_percentagePercentage

        Required

        A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

        A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

    • ordering_pausedboolean

      When true, a channel's new open orders are refused — the kitchen could not take another one. The till keeps selling regardless, and the setting is carried on the change feed so every surface hears it without a poll.

      default false

    • ordering_prep_time_minutesinteger · int32

      What an ordering page quotes for collection, in minutes. A location setting.

      ≥ 0 · default 0

    • overtime_threshold_hoursinteger · int32

      Hours a member may work in a week here before the rota warns. 0 is no threshold. Absent from a write leaves it as it is.

      0–168

    • phone_numberstring

      Contact number in E.164 format.

      ≤ 32 chars

    • profilestring · enum

      Nullable

      What this location trades as, so the till and the back office show or default what that trade uses. Absent means show everything, the current behaviour. Presentation and defaults only, never enforcement.

      hospitalityretail

    • return_window_daysinteger · int32

      Nullable

      This location's own returns window, in days (retail item 10). Absent means the merchant's window applies — a merchant whose sites differ sets it here, where the customer is told it. Zero is a deliberate no-window at this site.

      ≥ 0

    • service_chargeServiceCharge

      Nullable

      This location's discretionary service charge, added to the bill before anyone pays (order-ledger item 9). null means the location charges none.

      • amountMoney

        Nullable

        The charge as a fixed amount per bill. Exactly one of percentage and amount is set.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • discretionaryboolean

        Required

        Whether the guest may decline the charge. A charge that cannot be declined is a mandatory one and is taxed as such.

        default true

      • eat_in_onlyboolean

        Required

        Whether the charge applies to on-premises (eat-in) fulfilments only, or to every fulfilment.

        default false

      • percentagePercentage

        A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

        A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • tax_class_idstring · uuid

        Nullable

        The tax class this location's service charge is taxed under (decision record 0054), resolved by the same dated rules as goods and keyed by fulfilment type and date. A market's pack sets it to the outside-scope/zero class for a discretionary charge and the standard class for a mandatory one. Null means the charge is not taxed.

    • service_periodsarray of ServicePeriod

      The named services in a day, such as lunch and dinner, each with its own turn times and pacing. Absent from a write leaves them as they are.

      ≤ 20 items

      • namestring

        Required

        1–64 chars

      • daysarray of integer

        The weekdays it runs, 1 (Monday) to 7 (Sunday). Empty or absent is every day.

        ≤ 7 items

      • end_minuteinteger

        Required

        0–1440

      • pacing_coversinteger · int32

        The most covers that may arrive in one slot during this service. 0 is no cap.

        ≥ 0

      • start_minuteinteger

        Required

        0–1439

      • turn_timesarray of TurnTime

        How long a party stays during this service. Empty uses the location's.

        ≤ 20 items

        • max_party_sizeinteger · int32

          Required

          1–100

        • minutesinteger · int32

          Required

          1–1440

    • statusstring · enum

      Required

      activeinactive

    • tax_registration_numberstring

      This venue's own tax registration (a VAT number, say), as a receipt that prints this address carries it. Absent, the merchant's number applies — right for a single-country merchant and a franchise, wrong for a multi-country estate, where the taxpayer is per country and the merchant's number must not print above a foreign address (receipts-and-printing item 21).

      ≤ 32 chars

    • timezoneTimezone

      Required

      IANA time zone identifier.

      Used to resolve a location's business day for reporting and settlement.

      One of 348 values; see the schema.

    • tip_policystring · enum

      Whether this location's terminal prompts the guest for a tip, and what it offers. The till sends it with a card checkout so the terminal offers a tip, and the tip the guest adds lands on the payment. off takes the amount with no prompt; allow lets the guest add one on the terminal, using the options configured there.

      offallow

      default off

    • tip_presetsarray of Percentage

      What a card checkout at this location offers when it prompts for a tip, lowest first and none preselected: the till's tender sheet and a guest paying from their own phone both offer exactly these, and the charge applies the tapped one without rounding anywhere else. ["18", "20", "25"] is the platform default, which is what a location opens with; the merchant may change it like any other location setting.

      ≥ 1 items · ≤ 4 items · default [18 20 25]

    • turn_timesarray of TurnTime

      How long a party holds its table, by size: each entry covers parties up to its max_party_size, in order. Absent from a write leaves them as they are.

      ≤ 20 items

      • max_party_sizeinteger · int32

        Required

        1–100

      • minutesinteger · int32

        Required

        1–1440

    Responses

    • 200

      The updated location.

      Location · application/json
      • idstring · uuid

        Required

        UUIDv7 identifying the location.

      • typestring · enum

        Required

        mobile locations — market stalls, food vans — are expected to spend meaningful time offline, and are the reason the sync contract exists.

        physicalmobile

      • namestring

        Required

        Human-readable name, unique within the merchant. Appears in the dashboard and on receipts.

        1–255 chars

      • addressAddress

        A postal address.

        The address_line_* fields carry the most specific part of the address — street number, street name, building name. Less specific detail belongs in locality, administrative_district_level_* and country.

        The administrative_district_level_* fields are deliberately generic because their meaning is country-dependent: in the US level 1 is the state and level 2 the county; in the UK level 1 is the county.

        • address_line_1string

          Required

          First line of the address — street number, street name, building name.

          ≤ 255 chars

        • address_line_2string

          Second line of the address, if any.

          ≤ 255 chars

        • address_line_3string

          Third line of the address, if any.

          ≤ 255 chars

        • administrative_district_level_1string

          A civil entity within the country. The state in the US; the county in the UK.

          ≤ 128 chars

        • administrative_district_level_2string

          A civil entity within administrative_district_level_1.

          ≤ 128 chars

        • countryCountry

          Required

          ISO 3166-1 alpha-2 country code.

          ZZ is the unknown/unspecified placeholder.

          One of 250 values; see the schema.

        • localitystring

          The city or town.

          ≤ 128 chars

        • postal_codestring

          The postal or ZIP code.

          ≤ 32 chars

        • sublocalitystring

          A civil region within the locality, if any.

          ≤ 128 chars

      • auto_close_default_tip_percentagePercentage

        A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

        A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • auto_close_enabledboolean

        On, when this location's day closes, every open tab holding a card is settled with auto_close_default_tip_percentage; a tab with no card is left open and flagged left-overnight (tabs item 9).

      • booking_hoursarray of DaypartWindow

        The hours this location takes bookings, in its own timezone. Empty takes none. Absent from a write leaves them as they are.

        ≤ 28 items

        • daysarray of integer

          The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          1–1440

        • start_minuteinteger

          Required

          0–1439

      • break_threshold_minutesinteger · int32

        How long a shift at this location may run before a break is expected, in minutes. Zero disables the rule. Replaces the hard-coded six hours in the timesheet.

        ≥ 0 · default 360

      • business_day_start_local_timestring

        When this location's trading day begins, as a wall-clock time in its timezone (RFC 3339 partial-time, in the shape Square uses for start_local_time). A sale before it belongs to the previous business day, so a bar's 00:30 round counts towards last night's takings rather than today's.

        Defaults to 04:00, as Toast's closeout hour does: nothing that opens before four in the morning is affected, and every late-night venue is. Changing it affects sales from then on; days already traded keep the business date they were given.

        pattern ^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$ · default 04:00:00

      • business_emailstring · email

        The address a guest's reply to an email this venue sent should reach: the Reply-To on the guest messages this location's emails send. Empty means a reply goes to the platform, which answers for the venue.

        ≤ 254 chars

      • business_hoursarray of DaypartWindow

        The hours this location trades, in its own timezone, which the marketplace shows as open or closed. Apart from booking_hours. Absent from a write leaves them as they are.

        ≤ 8 items

        • daysarray of integer

          The weekdays this window opens on, 1 (Monday) through 7 (Sunday). An empty or absent list is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          1–1440

        • start_minuteinteger

          Required

          0–1439

      • cash_stepMoney

        A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

        The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

        Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • coordinatesCoordinates

        Nullable

        Where the location is, placed by the merchant, which the marketplace sorts guests' results by. null until placed. Absent from a write leaves it as it is.

        • latitudenumber · double

          Required

          -90–90

        • longitudenumber · double

          Required

          -180–180

      • created_atTimestamp

        RequiredRead only

        Server-assigned RFC 3339 timestamp, always UTC.

        Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

      • currencyCurrency

        Required

        ISO 4217 currency code.

        Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

        One of 182 values; see the schema.

      • descriptionstring

        What the location says about itself on the marketplace. Absent from a write leaves it as it is.

        ≤ 280 chars

      • favoritesarray of string · uuid

        A shop's favourites, Square's Favorites and Toast's speed menu: up to twenty-four of its products, in this order, which a till in retail shows first, before the catalogue. Empty means the catalogue alone. Chosen in the back office; a device never writes it.

        ≤ 24 items · default []

      • kds_amber_minutesinteger · int32

        How long a kitchen ticket may wait (in minutes) before a kitchen display colours it amber. A location setting; the till paints from it.

        ≥ 1 · default 10

      • kds_red_minutesinteger · int32

        How long a kitchen ticket may wait (in minutes) before a kitchen display colours it red. A location setting; the till paints from it.

        ≥ 1 · default 20

      • labor_budgetMoney

        Nullable

        What a week's labor here is planned to cost, which the rota compares against. null sets none. Absent from a write leaves it as it is.

        • amountinteger · int64

          Required

          The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

        • currencyCurrency

          Required

          ISO 4217 currency code.

          Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

          One of 182 values; see the schema.

      • labor_target_percentagePercentage

        Nullable

        What labor here should cost as a share of net sales, which Home and the labor report set the day's cost against. null sets none. Absent from a write leaves it as it is.

        pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • language_codeLanguageCode

        IETF BCP 47 language tag.

        Used for receipts, dashboard copy and buyer-facing text.

        One of 30 values; see the schema.

      • merchant_idstring · uuid

        RequiredRead only

        The owning merchant. Read-only and derived from the caller's token — a location can never be moved between merchants.

      • min_break_minutesinteger · int32

        The least a break that is taken should be, in minutes. A shift with a break shorter than this still counts as missed.

        ≥ 0 · default 0

      • online_bookingOnlineBooking

        Whether guests may book this location themselves on its booking page, how far ahead and for how many, and how much of the room is kept for walk-ins. Absent from a write leaves it as it is.

        • days_aheadinteger · int32

          Required

          0–365

        • deposit_per_personMoney

          A monetary amount in a specific currency: Square's Money, and Stripe's amount beside its currency.

          The amount is always an integer count of the currency's minor unit — pence for GBP, cents for USD. Zero-decimal currencies such as JPY have a minor unit equal to their major unit, so {"amount": 500, "currency": "JPY"} is ¥500 while {"amount": 500, "currency": "GBP"} is £5.00.

          Floating point is never used for money anywhere in this API. Binary floats cannot represent most decimal fractions exactly, so accumulating them across the line items of an order produces totals that disagree with the printed receipt by a penny. Integer minor units make every arithmetic operation exact.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • enabledboolean

          Required

        • max_party_sizeinteger · int32

          Required

          The largest party a guest may book online. 0 is no limit.

          0–100

        • waitlist_enabledboolean

          Whether guests may join this location's waitlist from its own page. Distinct from enabled: a venue may take bookings online and not queue walk-ins from the web, or queue them and take no bookings. Absent from a write leaves it as it is.

        • walk_in_percentagePercentage

          Required

          A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

          A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

      • ordering_auto_acceptboolean

        Read only

        Whether an order from the ordering page is accepted as it arrives, rather than waiting for somebody to take it on. Changed on the ordering settings, not by writing the location.

        default false

      • ordering_enabledboolean

        Read only

        Whether guests can order from this location's ordering page. Changed on the ordering settings, not by writing the location.

        default false

      • ordering_handlestring

        Read only

        The ordering page's name: its subdomain on the guest ordering site. Absent until one is chosen. Changed on the ordering settings, not by writing the location.

        ≤ 63 chars

      • ordering_pausedboolean

        When true, a channel's new open orders are refused — the kitchen could not take another one. The till keeps selling regardless, and the setting is carried on the change feed so every surface hears it without a poll.

        default false

      • ordering_prep_time_minutesinteger · int32

        What an ordering page quotes for collection, in minutes. A location setting.

        ≥ 0 · default 0

      • overtime_threshold_hoursinteger · int32

        Hours a member may work in a week here before the rota warns. 0 is no threshold. Absent from a write leaves it as it is.

        0–168

      • phone_numberstring

        Contact number in E.164 format.

        ≤ 32 chars

      • profilestring · enum

        Nullable

        What this location trades as, so the till and the back office show or default what that trade uses. Absent means show everything, the current behaviour. Presentation and defaults only, never enforcement.

        hospitalityretail

      • return_window_daysinteger · int32

        Nullable

        This location's own returns window, in days (retail item 10). Absent means the merchant's window applies — a merchant whose sites differ sets it here, where the customer is told it. Zero is a deliberate no-window at this site.

        ≥ 0

      • service_chargeServiceCharge

        Nullable

        This location's discretionary service charge, added to the bill before anyone pays (order-ledger item 9). null means the location charges none.

        • amountMoney

          Nullable

          The charge as a fixed amount per bill. Exactly one of percentage and amount is set.

          • amountinteger · int64

            Required

            The amount, as a whole number of the currency's minor unit. May be negative to express a refund, discount or credit.

          • currencyCurrency

            Required

            ISO 4217 currency code.

            Determines the minor unit that Money.amount is expressed in. Zero-decimal currencies such as JPY have a minor unit equal to the major unit.

            One of 182 values; see the schema.

        • discretionaryboolean

          Required

          Whether the guest may decline the charge. A charge that cannot be declined is a mandatory one and is taxed as such.

          default true

        • eat_in_onlyboolean

          Required

          Whether the charge applies to on-premises (eat-in) fulfilments only, or to every fulfilment.

          default false

        • percentagePercentage

          A share of a whole, from "0" to "100", as a percentage in a decimal string with at most four decimal places, as Square's percentage and Stripe Tax's percentage_decimal are: UK VAT at 20% is "20", and an 8.875% US sales tax is "8.875".

          A string because a JSON number is a binary float to most parsers, and a float cannot hold most decimal fractions exactly (RFC 7493 §2.2). Tenvelo computes with a percentage as an integer in parts per million ("8.875" is 88750), which every four-place percentage is exactly. A client that computes with one should read the digits the same way, never through a float.

          pattern ^(100(\.0{1,4})?|(0|[1-9][0-9]?)(\.[0-9]{1,4})?)$

        • tax_class_idstring · uuid

          Nullable

          The tax class this location's service charge is taxed under (decision record 0054), resolved by the same dated rules as goods and keyed by fulfilment type and date. A market's pack sets it to the outside-scope/zero class for a discretionary charge and the standard class for a mandatory one. Null means the charge is not taxed.

      • service_periodsarray of ServicePeriod

        The named services in a day, such as lunch and dinner, each with its own turn times and pacing. Absent from a write leaves them as they are.

        ≤ 20 items

        • namestring

          Required

          1–64 chars

        • daysarray of integer

          The weekdays it runs, 1 (Monday) to 7 (Sunday). Empty or absent is every day.

          ≤ 7 items

        • end_minuteinteger

          Required

          0–1440

        • pacing_coversinteger · int32

          The most covers that may arrive in one slot during this service. 0 is no cap.

          ≥ 0

        • start_minuteinteger

          Required

          0–1439

        • turn_timesarray of TurnTime

          How long a party stays during this service. Empty uses the location's.

          ≤ 20 items

          • max_party_sizeinteger · int32

            Required

            1–100

          • minutesinteger · int32

            Required

            1–1440

      • statusstring · enum

        Required

        activeinactive

      • tax_registration_numberstring

        This venue's own tax registration (a VAT number, say), as a receipt that prints this address carries it. Absent, the merchant's number applies — right for a single-country merchant and a franchise, wrong for a multi-country estate, where the taxpayer is per country and the merchant's number must not print above a foreign address (receipts-and-printing item 21).

        ≤ 32 chars

      • timezoneTimezone

        Required

        IANA time zone identifier.

        Used to resolve a location's business day for reporting and settlement.

        One of 348 values; see the schema.

      • tip_policystring · enum

        Whether this location's terminal prompts the guest for a tip, and what it offers. The till sends it with a card checkout so the terminal offers a tip, and the tip the guest adds lands on the payment. off takes the amount with no prompt; allow lets the guest add one on the terminal, using the options configured there.

        offallow

        default off

      • tip_presetsarray of Percentage

        What a card checkout at this location offers when it prompts for a tip, lowest first and none preselected: the till's tender sheet and a guest paying from their own phone both offer exactly these, and the charge applies the tapped one without rounding anywhere else. ["18", "20", "25"] is the platform default, which is what a location opens with; the merchant may change it like any other location setting.

        ≥ 1 items · ≤ 4 items · default [18 20 25]

      • turn_timesarray of TurnTime

        How long a party holds its table, by size: each entry covers parties up to its max_party_size, in order. Absent from a write leaves them as they are.

        ≤ 20 items

        • max_party_sizeinteger · int32

          Required

          1–100

        • minutesinteger · int32

          Required

          1–1440

      • updated_atTimestamp

        RequiredRead only

        Server-assigned RFC 3339 timestamp, always UTC.

        Server-assigned because device clocks drift and cannot be trusted for ordering — a till that has been powered off for a week may come back with a clock hours out. Where the device's own view of time matters it is carried separately in client_created_at.

      • versionVersion

        RequiredRead only

        Optimistic concurrency version, raised by the server on every write. A version is never lower than one already returned for the resource, though it may rise by more than one.

        Returned in the ETag response header as well as in the body. Send it back in If-Match on an update and the write is rejected with 412 if anyone else has written since — which is what stops two tills silently overwriting each other's edit to the same product when both come back online at once.

        ≥ 1

    • 400

      The request could not be parsed. Malformed JSON, a bad query parameter, or a header that failed to decode, among them an API-Version later than the server speaks or not a date (api-version-unknown, with the server's own in api_version).

      Distinct from 422: a 400 never reached validation, so invalid_params is absent. Retrying without changing the request will fail again, except that a request refused for its API-Version goes once the server is updated.

    • 401

      No credentials, or credentials that could not be verified — missing bearer token, malformed JWT, expired token, or a signature that failed against the issuer's JWKS.

      Refresh the token and retry once. Repeated 401 after a refresh means the device needs to re-enrol.

    • 403

      Authenticated, but not permitted. The token is valid and its merchant was resolved, but the caller's role does not allow this operation, or the target belongs to a different merchant.

      Cross-tenant access is reported as 403 on a resource the caller may not see, and as 404 where even confirming existence would leak information. Retrying will not help.

    • 404

      No such resource, or none visible to this caller.

      Also returned instead of 403 where acknowledging existence would itself leak information — so a 404 does not prove the id is unused globally, only that it is not yours.

    • 409

      The request conflicts with current state — a uniqueness constraint, or an attempt to mutate an order that is already completed or voided.

      Unlike 412, re-reading and retrying unchanged will not resolve it; the request itself has to change.

    • 410

      The request names an API-Version this server no longer serves (docs/decisions/0011). Nothing in it was read. api_version names the version the server speaks: the client is behind, and sends the request again once it is updated.

    • 412

      The If-Match version did not match the resource's current version: someone else wrote since you read.

      This is the expected, healthy outcome of two clients editing the same record — not an error condition to suppress. Re-read the resource, re-apply your change on top of the new state, and retry with the fresh ETag.

    • 415

      The request Content-Type is not supported. This API accepts application/json on all mutations.

    • 422

      The request parsed but failed validation.

      invalid_params lists every failing field with a JSON Pointer, not just the first, so a client can mark up a whole form in one pass rather than making the user fix errors one round trip at a time.

      Also returned when an Idempotency-Key is replayed with a different body, and when device-computed order totals disagree with the server's recomputation.

    • 429

      Rate limit exceeded. Honour Retry-After rather than applying your own backoff.

      A fleet of tills coming back online together after an outage is the realistic cause, which is exactly when uncoordinated client-side retry turns a brief outage into a sustained one. The limit is per process, and per site for what records trade there — a request spends its site's budget, and a till's own smaller one inside it — and per (client, merchant) for everything else; no RateLimit field is sent, so this response and its Retry-After are the whole of the contract.

    • 500

      Something failed on our side. trace_id identifies the request in our tracing — quote it in a support ticket.

      The body never carries internal detail: no SQL, no stack traces, no upstream error strings. Safe to retry with the same Idempotency-Key.

    • 503

      Temporarily unable to serve the request — a dependency is down or the service is shedding load.

      Retry with the same Idempotency-Key after Retry-After. This is always safe: a request that did take effect before the failure will be recognised as a replay.

  7. DELETE/v1/locations/{id}

    Delete a location

    No. deleteLocationAuth bearer

    Soft-deletes a location. Fails with 409 while devices are still assigned to it.

    Parameters

    • idpath · string · uuid

      Required

      UUIDv7 of the resource.

      For resources a device can originate — orders, and their line items — this id is minted by the client before the record is ever synced, which is what makes an offline create idempotent.

    • If-Matchheader · string

      Required

      The ETag from the read that produced the value you are updating.

      Required on updates, not optional, because "last write wins" is the wrong default for a catalogue two managers might edit at once. If anything has been written since your read, the request is rejected with 412 and you re-read and re-apply.

      Use * to mean "write regardless of current version" — an explicit, greppable override rather than the silent default.

    Responses

    • 204

      The location was deleted.

    • 400

      The request could not be parsed. Malformed JSON, a bad query parameter, or a header that failed to decode, among them an API-Version later than the server speaks or not a date (api-version-unknown, with the server's own in api_version).

      Distinct from 422: a 400 never reached validation, so invalid_params is absent. Retrying without changing the request will fail again, except that a request refused for its API-Version goes once the server is updated.

    • 401

      No credentials, or credentials that could not be verified — missing bearer token, malformed JWT, expired token, or a signature that failed against the issuer's JWKS.

      Refresh the token and retry once. Repeated 401 after a refresh means the device needs to re-enrol.

    • 403

      Authenticated, but not permitted. The token is valid and its merchant was resolved, but the caller's role does not allow this operation, or the target belongs to a different merchant.

      Cross-tenant access is reported as 403 on a resource the caller may not see, and as 404 where even confirming existence would leak information. Retrying will not help.

    • 404

      No such resource, or none visible to this caller.

      Also returned instead of 403 where acknowledging existence would itself leak information — so a 404 does not prove the id is unused globally, only that it is not yours.

    • 409

      The request conflicts with current state — a uniqueness constraint, or an attempt to mutate an order that is already completed or voided.

      Unlike 412, re-reading and retrying unchanged will not resolve it; the request itself has to change.

    • 410

      The request names an API-Version this server no longer serves (docs/decisions/0011). Nothing in it was read. api_version names the version the server speaks: the client is behind, and sends the request again once it is updated.

    • 412

      The If-Match version did not match the resource's current version: someone else wrote since you read.

      This is the expected, healthy outcome of two clients editing the same record — not an error condition to suppress. Re-read the resource, re-apply your change on top of the new state, and retry with the fresh ETag.

    • 429

      Rate limit exceeded. Honour Retry-After rather than applying your own backoff.

      A fleet of tills coming back online together after an outage is the realistic cause, which is exactly when uncoordinated client-side retry turns a brief outage into a sustained one. The limit is per process, and per site for what records trade there — a request spends its site's budget, and a till's own smaller one inside it — and per (client, merchant) for everything else; no RateLimit field is sent, so this response and its Retry-After are the whole of the contract.

    • 500

      Something failed on our side. trace_id identifies the request in our tracing — quote it in a support ticket.

      The body never carries internal detail: no SQL, no stack traces, no upstream error strings. Safe to retry with the same Idempotency-Key.

    • 503

      Temporarily unable to serve the request — a dependency is down or the service is shedding load.

      Retry with the same Idempotency-Key after Retry-After. This is always safe: a request that did take effect before the failure will be recognised as a replay.