From 19 June 2026, the EU requires a "withdrawal button" in online shops that let consumers withdraw from a distance contract (Art. 11a of the Consumer Rights Directive, introduced by Directive (EU) 2023/2673). Customers must be able to declare their withdrawal right inside the shop, without a login and without detours.
go~mus delivers the withdrawal across all four routes you sell on: it ships automatically in the standalone shop, in the embedded bundle via a flow switch, as a web component, and through a public API endpoint. Pick the route that fits your integration.
This page is technical integration guidance, not legal advice. Whether and how the rule applies to you is something to settle with your own legal team. For a non-technical overview (legal framework, affected products, back-office management) see Features: Withdrawal.
Standalone shop
Shops shipped by go~mus have the withdrawal button on board automatically. You do not have to do or build anything.
Bundle
If you embed the go~mus bundle, you open the withdrawal form via the same flow switch as tickets or events:
<a href="https://<your-shop>" data-gomus-flow="withdrawal">Withdrawal</a>
As an overlay on a button, or inline via <div data-gomus-embed-inline data-gomus-flow="withdrawal"></div>. The form appears as a standalone step (heading, notice, fields), no cart. Live demo on the shop page.
Web components
If your shop embeds the go~mus web components, the withdrawal button ships as a dedicated element from version 3.3.0. You don't have to build anything against the API:
<go-withdrawal-form></go-withdrawal-form>
The component renders the full form (order number, first and last name, email, optional note), validates the required fields, submits the withdrawal and fires a go-success event on success. It sets the shop scope (the X-Shop-Url header) from your go~mus configuration, so you don't pass it yourself. The custom attribute lets you take over the markup for your own styling.
You place the button and the subpage it needs yourself; the component does not wire itself into your shop.
Component list, properties and a live Storybook example are in the web components docs.
API
If you build without our web components, you create the form yourself and post against a single endpoint:
POST /api/v4/orders/withdrawals
The endpoint is public and unauthenticated. That is by design: withdrawal must be possible as a guest, without a login (Recital 37 of the directive). Instead of a token, you identify the shop through a header.
| Header | Required | Meaning |
|---|---|---|
X-Shop-Url | yes | Hostname of the shop the withdrawal is scoped to |
Content-Type | yes | application/json |
Request body:
| Field | Required | Description |
|---|---|---|
order_id | yes | Order number the withdrawal refers to |
first_name | yes | Customer's first name |
last_name | yes | Customer's last name |
email | yes | Customer's email address |
note | no | Free text, e.g. which items to withdraw. Never required. |
curl -X POST "https://demo.gomus.de/api/v4/orders/withdrawals" \
-H "Content-Type: application/json" \
-H "X-Shop-Url: shop.example-museum.de" \
-d '{
"order_id": "12345",
"first_name": "Erika",
"last_name": "Mustermann",
"email": "kunde@example.com",
"note": "Only the book, please."
}'
Responses:
| Status | Meaning |
|---|---|
201 | Withdrawal received. The body is empty, do not parse it as JSON. |
403 | Unknown shop, or order_id names no order of that shop placed within the last 14 months. Order ids are guessable; that is accepted. |
422 | Validation error. Body holds errors with field-level messages, e.g. { "errors": { "email": ["is invalid"] } }. |
429 | Rate limit exceeded. |
Rate limits: 10 requests per minute per client IP, 30 per minute per X-Shop-Url. Exceeding either returns 429.
Withdrawal is not cancellation
The withdrawal endpoint cancels nothing automatically. It records the customer's declaration and stores it. The museum team reviews each withdrawal and handles cancellation and refund afterwards, by hand. This is deliberate: a withdrawal is a legal declaration of intent, not a self-triggering action.
The actual cancellation of an order runs through a different, authenticated call (POST /api/v4/orders/:id/cancellations) made by backoffice or permitted API users. Details in Orders.
Related pages
- Web components - the
<go-withdrawal-form>component and the Storybook - Orders - order lifecycle, cancellation and refund
- Errors - 422 validation and the error format
- Authentication - why this endpoint deliberately needs no token