Skip to content

Versioning and deprecations

The widget is delivered from a single URL and updates without action on your part. This page states what that update can change.

<script src="https://app.useservice.app/widget/widget.js" async></script>

That address is stable. It redirects to a content-hashed file:

ResponseCache-Control
/widget/widget.js — 302 to the current buildpublic, max-age=300, must-revalidate
/widget/widget.<hash>.js — the build itselfpublic, max-age=31536000, immutable

So a browser rechecks the stable address every five minutes and caches the file it is sent for a year. A new release reaches your visitors within minutes of shipping.

Copying the hashed URL into your page, self-hosting the file, or letting a CMS caching plugin rewrite the address pins you to one build. You will stop receiving fixes, including security fixes. Load the stable address.

ServiceWidget.version; // "2.8.0"

This is the version of the JavaScript API — the options, methods and events on this site — not of the funnel the guest sees. Report it when raising an issue.

Anything the guest sees. Layout, copy, steps, styling, added fields, changed wording, new booking states. The funnel is ours to change and it changes often.

Write your integration so it does not depend on the widget’s internals:

  • Do not query the widget’s DOM, its shadow root, or any class name.
  • Do not depend on the number or order of steps in the funnel.
  • Do not treat reservation.status as a closed set — new values are added.

The API on this site is what you build against, and we do not break it:

  • Options accepted by ServiceWidget.create().
  • Methods on the instance, and their behaviour.
  • Event names, and the fields already present on their payloads.
  • The hint names accepted by setContext() and by URL parameters.
  • The token format, its claim names, and the meaning of locked.
  • The query parameters appended to your return_url.

Payloads gain fields. A new key on an event payload or a bootstrap response is not a breaking change, so read the fields you need rather than asserting on the whole object.

data-mode="manual" was the script tag’s name for popover, and ServiceWidget.open({ slug }) opened a widget the global created on demand. Both were removed on 6 August 2026. data-mode="manual" now behaves like any unrecognised value and falls back to inline; open() takes no argument and drives the widget the script tag mounted.

An earlier version of this page said both were “accepted indefinitely” and live on restaurant sites that would never be edited again. That was an assumption, not a fact: Service publishes every embed snippet in use, and the back office now emits data-mode="popover". Removing them cost nothing and removed a second name for one thing.

One consequence is worth stating plainly: one script tag drives one restaurant. A [data-service-widget-open] trigger carrying its own data-slug used to get a widget of its own. It no longer does — it is ignored, with an explanation on the console, rather than quietly opening the restaurant the script tag serves. For several restaurants on one page, call create() per restaurant and keep the handles.

There is no deprecation timetable here to point at, because nothing is deprecated. If that changes, a breaking change would be announced on this page before it shipped, with the old behaviour retained for the announced period. Until then, the guarantee above is the whole policy.