{
    "openapi": "3.1.0",
    "info": {
        "title": "HikaShop Connector API",
        "version": "6.6.0",
        "description": "The connector plugin ships inside HikaShop Business and answers JSON over HTTPS. The mobile\napplication is one client of it; anything it does, your own code can do.\n\nEvery response carries the same envelope, `{\"data\": …, \"meta\": …, \"error\": null}`, and every route\nexcept `POST /pair` carries a device token as `Authorization: Bearer <token>`. A token holds the\nscopes `read` and optionally `write`, and the operator it is bound to keeps their own access\nlevels, so a device may hold `write` and still be refused an order its operator cannot see.\n\nThe base path is a plugin parameter and a shop can move it. Nothing else here changes between\nshops.\n\n## Pairing a device\n\nA client never sees the merchant's password. It is given a **pairing code** instead, generated in\n**System > App Devices** of the backend, and exchanges it once for a token of its own.\n\nThe code is nine characters, lives five minutes, may be tried five times before it dies, and can\nonly be spent once. `POST /pair` is rate limited to thirty attempts per minute per address, which\nis the only route that answers without a token.\n\nWhat comes back is the token, the scopes the code granted, and the id of the device row. The token\nis shown once and stored only as a SHA-256 hash, so a device that loses it pairs again rather than\nrecovering it. Revoking a device is deleting its row in that same screen, and every token it held\nstops working at once.\n\n```\ncurl -X POST \"$SHOP/hikashop-api/v1/pair\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"code\": \"K7QM-2F84\", \"device_name\": \"Counter tablet\" }'\n\n# then, for everything else\ncurl \"$SHOP/hikashop-api/v1/products\" \\\n  -H \"Authorization: Bearer $TOKEN\"\n```\n\n## Scopes and access levels\n\nTwo separate checks run on every request, and the narrower one wins.\n\nThe **scope** is what the device may do at all: `read`, and `write` if the pairing code granted it.\nA device without `write` is refused every route that changes anything, whoever holds it.\n\nThe **access levels** are the shop's own, belonging to the operator the device is bound to. They\ndecide which records that person may see and change, exactly as they do in the backend. So a device\nholding `write` can still be refused an order, and a device holding only `read` sees a smaller\ncatalogue than another one.\n\nThis is why an integration should be given its own device rather than borrowing one: revoke it and\nnothing else is disturbed, and its operator's access levels are the ceiling on what it can reach.\n\n```\n{\n  \"data\": null,\n  \"error\": {\n    \"code\": \"forbidden\",\n    \"message\": \"This device does not have the required scope.\"\n  }\n}\n```\n\n## The envelope, errors and paging\n\nEvery JSON answer has the same three keys. `data` is the payload, `meta` carries paging and other\ncontext when there is any and is `null` otherwise, and `error` is `null` on success.\n\nOn failure `data` is `null` and `error` holds a stable `code` and a human `message`. Read the code,\nnot the message: the message is written for a person and may be translated or reworded, the code is\nwhat your own logic should branch on.\n\nListings page with `start` and `limit` in the query, and answer with `start`, `limit` and `total` in\nthe envelope's `meta`. `total` counts the rows matching the filter before paging, so it is how you\nknow there is another page. `limit` is capped, usually at a hundred, and asking for more silently\ngets you the cap rather than an error.\n\nOne thing to note about a listing: `data` is the list itself, not an object wrapping it. The paging\nlives in `meta`.\n\n- `invalid_request` (400) A required field is missing or malformed.\n- `unauthorized` (401) No token, or a token that is unknown, revoked or unpublished.\n- `forbidden` (403) The device lacks the scope, or the operator lacks the access level.\n- `not_found` (404) No such record, or no such route. Also returned when the operator may not see the record, so that it cannot be probed for.\n- `too_many_requests` (429) Rate limited. Only /pair does this.\n\n```\n{\n  \"data\": [ … ],\n  \"meta\": { \"start\": 0, \"limit\": 20, \"total\": 307 },\n  \"error\": null\n}\n```\n\n## Calling it from a browser\n\nThe API answers cross-origin requests, because the application is a web application as well as a\nphone one. `Access-Control-Allow-Origin` is `*`, the allowed methods are GET, POST, PUT, DELETE and\nOPTIONS, and the allowed headers are `Authorization`, `Content-Type` and `X-Hikashop-Token`. A\npreflight is answered immediately and may be cached for a day.\n\n`*` with a bearer token is deliberate and safe in the way cookies would not be: nothing is sent\nautomatically by the browser, so a page on another origin can only call this API if it already\nholds a token, and a token is only ever obtained by pairing.\n\nSend the token in the `Authorization` header. Never put it in the query string, where it would be\nwritten to every access log between you and the shop.\n\n```\nOPTIONS /hikashop-api/v1/products\n\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\nAccess-Control-Allow-Headers: Authorization, Content-Type, X-Hikashop-Token\nAccess-Control-Max-Age: 86400\n```\n\n## Adding your own routes\n\nA HikaShop plugin can serve paths of its own through the same base path, the same envelope and the\nsame authentication, by listening to three events.\n\n`onConnectorBeforeRoute` fires before any matching, so it can intercept a path the connector also\nserves. `onConnectorRoute` fires only when nothing matched, which is where a new path belongs.\n`onConnectorBeforeResponse` fires just before the JSON is written, for adding a field to an answer\nsomebody else built.\n\nThe listener receives one object by reference, carrying `path` (the part after the base path),\n`method`, `base_path`, `response`, and `handled`. Authenticate with `requireScope()` exactly as the\nconnector's own routes do, answer through `$ctx->response`, and set `$ctx->handled = true` so the\nrouter stops rather than falling through to its 404.\n\n```\npublic function onConnectorRoute(&$ctx) {\n    if ($ctx->path !== 'warehouse/stock' || $ctx->method !== 'GET')\n        return;\n\n    $device = HikashopConnectorAuth::requireScope($ctx->response, 'read');\n    if ($device === null)\n        return;          // it has already answered 401 or 403\n\n    $ctx->response->data(array('pallets' => $this->countPallets()));\n    $ctx->handled = true;\n}\n```",
        "license": {
            "name": "Proprietary, ships with HikaShop Business"
        }
    },
    "servers": [
        {
            "url": "https://your-shop.tld/hikashop-api/v1",
            "description": "The base path is a plugin parameter and a shop can move it."
        }
    ],
    "components": {
        "securitySchemes": {
            "deviceToken": {
                "type": "http",
                "scheme": "bearer",
                "description": "The token returned once by POST /pair."
            }
        },
        "schemas": {
            "Error": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "null"
                    },
                    "error": {
                        "type": "object",
                        "properties": {
                            "code": {
                                "type": "string"
                            },
                            "message": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        }
    },
    "security": [
        {
            "deviceToken": []
        }
    ],
    "paths": {
        "/site": {
            "get": {
                "operationId": "get-site",
                "summary": "What this shop is",
                "description": "The first call a client makes. It says what it has connected to, who it is connected as, and what\nthat operator is allowed to do, which is enough to draw an interface without asking for anything\nit will only be refused.\n\nNothing here changes often. Cache it, and use `GET /version` to know when to look again.",
                "tags": [
                    "site"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "app": {
                                                    "type": "string",
                                                    "description": "Always `hikashop-connector`. A cheap way to be sure you are talking to this API and not to something else answering on that path."
                                                },
                                                "api_version": {
                                                    "type": "string",
                                                    "description": "Semver of the API itself, not of HikaShop. A minor bump adds fields or routes, a major one breaks something."
                                                },
                                                "site_name": {
                                                    "type": "string",
                                                    "description": "What the site calls itself, which is what a merchant recognises the shop by."
                                                },
                                                "hikashop_version": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The HikaShop release running there."
                                                },
                                                "cms": {
                                                    "type": "object",
                                                    "properties": {
                                                        "name": {
                                                            "type": "boolean",
                                                            "description": "`joomla` or `wordpress`."
                                                        },
                                                        "version": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ],
                                                            "description": "The CMS release."
                                                        }
                                                    },
                                                    "description": "What it is running on."
                                                },
                                                "edition": {
                                                    "type": "string",
                                                    "description": "`starter`, `essential` or `business`. This API only answers on Business, so in practice it is `business` unless the licence has lapsed."
                                                },
                                                "logo": {
                                                    "type": "string",
                                                    "description": "The shop's logo as an absolute URL, empty when none is set. The same setting the invoices use."
                                                },
                                                "currency": {
                                                    "type": "object",
                                                    "properties": {
                                                        "default": {
                                                            "type": "integer",
                                                            "description": "The currency id, a row in the shop's own table, not an ISO code."
                                                        }
                                                    },
                                                    "description": "The shop's money."
                                                },
                                                "price_with_tax": {
                                                    "type": "boolean",
                                                    "description": "Whether prices are shown to customers with tax included. Display only: the prices in this API are as stored."
                                                },
                                                "operator": {
                                                    "type": "object",
                                                    "properties": {
                                                        "id": {
                                                            "type": "integer",
                                                            "description": "`0` when the device is bound to nobody, which is a device paired without an operator."
                                                        },
                                                        "name": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ],
                                                            "description": "Their display name."
                                                        },
                                                        "role": {
                                                            "type": "string",
                                                            "description": "`admin` when they may manage the component, `staff` otherwise."
                                                        }
                                                    },
                                                    "description": "The user the device is bound to."
                                                },
                                                "scopes": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "What this device may do: `read`, and `write` when it was granted."
                                                },
                                                "permissions": {
                                                    "type": "object",
                                                    "description": "What the operator's access levels allow, keyed by resource (`product`, `order`, `category`, `discount`, `user`, `zone`, `characteristic`, `massaction`, `dashboard`), each with `view`, `manage` and `delete`. Use it to leave controls out rather than showing a screen full of refusals. Its keys are the resources this HikaShop knows about, so an add-on can add one.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "capabilities": {
                                                    "type": "object",
                                                    "properties": {
                                                        "pos": {
                                                            "type": "boolean",
                                                            "description": "Reserved for the point of sale, false for now."
                                                        },
                                                        "push": {
                                                            "type": "boolean",
                                                            "description": "Reserved for push notifications, false for now."
                                                        },
                                                        "multivendor": {
                                                            "type": "boolean",
                                                            "description": "Whether HikaMarket is installed."
                                                        }
                                                    },
                                                    "description": "What this shop can do beyond the basics."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/settings": {
            "get": {
                "operationId": "get-settings",
                "summary": "The settings that decide how prices read",
                "description": "The handful of configuration flags a client needs in order to show the same figures the shop's own\npages show. They are read only here; they are changed in the backend.",
                "tags": [
                    "settings"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "product_contact": {
                                                    "type": "boolean",
                                                    "description": "Whether products can be enquired about rather than bought."
                                                },
                                                "product_waitlist": {
                                                    "type": "boolean",
                                                    "description": "Whether customers can join a waiting list for something out of stock."
                                                },
                                                "price_with_tax": {
                                                    "type": "boolean",
                                                    "description": "Show prices with tax included."
                                                },
                                                "floating_tax_prices": {
                                                    "type": "boolean",
                                                    "description": "Whether the tax shown depends on the customer, which means a price cannot be cached across customers."
                                                },
                                                "show_original_price": {
                                                    "type": "boolean",
                                                    "description": "Show the price before a discount alongside the discounted one."
                                                },
                                                "round_calculations": {
                                                    "type": "integer",
                                                    "description": "When rounding happens during a calculation. Match it or your totals will differ from the shop by a cent."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/version": {
            "get": {
                "operationId": "get-version",
                "summary": "Change tokens for the cacheable resources",
                "description": "Three opaque tokens, one for each resource worth caching. A token changes when its resource does,\nso a client keeps the copy it has until the token moves.\n\nCompare them, do not read them. They are strings today and their meaning is deliberately not part\nof this contract.\n\nThis is what makes a dictionary of several thousand strings affordable: fetch it once, ask this\ncheap route afterwards.",
                "tags": [
                    "version"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "i18n": {
                                                    "type": "string",
                                                    "description": "Moves when the shop's translations change."
                                                },
                                                "statuses": {
                                                    "type": "string",
                                                    "description": "Moves when an order status is added, renamed or unpublished."
                                                },
                                                "languages": {
                                                    "type": "string",
                                                    "description": "Moves when the shop's languages change."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/statuses": {
            "get": {
                "operationId": "get-statuses",
                "summary": "The shop's order statuses",
                "description": "Every published order status, in the order the backend shows them. A shop invents its own, so this\nlist is not a fixed set and should never be hard coded.\n\nThe `namekey` is the identifier to send to `POST /orders/{id}/status`; the `name` is for a person\nto read.",
                "tags": [
                    "statuses"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "namekey": {
                                                        "type": "string",
                                                        "description": "The identifier. This is what you send when changing an order."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Translated into the operator's language, ready to display."
                                                    },
                                                    "label_key": {
                                                        "type": "string",
                                                        "description": "The translation key behind that name, if you would rather translate it yourself."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "The colour the backend uses for this status, empty when none is set."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/i18n": {
            "get": {
                "operationId": "get-i18n",
                "summary": "HikaShop's own translation of a locale",
                "description": "The shop's translation dictionary for one locale, so that a client can name things exactly as the\nmerchant's own site names them, including whatever they have overridden.\n\nIt is large. Cache it against the `i18n` token from `GET /version` rather than fetching it again.",
                "tags": [
                    "i18n"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "locale",
                        "in": "query",
                        "required": false,
                        "description": "A HikaShop language tag such as `en-GB`. Falls back to the site language when it is not installed.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "locale": {
                                                    "type": "string",
                                                    "description": "The locale actually served, which may not be the one asked for."
                                                },
                                                "strings": {
                                                    "type": "object",
                                                    "description": "Translation key to translated text. Thousands of keys, and a shop can add or override any of them, so there is no list to give.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/languages": {
            "get": {
                "operationId": "get-languages",
                "summary": "The shop's languages",
                "description": "Which languages the shop publishes, and whether content translation is switched on at all.\n\nWhen `enabled` is false the shop is single-language and the translation routes have nothing to do.\nThe default language is marked and comes last, because it is the one already being edited on the\nmain form rather than a translation of it.",
                "tags": [
                    "languages"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "enabled": {
                                                    "type": "boolean",
                                                    "description": "Whether this shop translates its content. False on a single-language site."
                                                },
                                                "languages": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The language id in the shop's table."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "The tag, such as `fr-FR`."
                                                            },
                                                            "shortcode": {
                                                                "type": "string",
                                                                "description": "The lower-case underscored form, such as `fr_fr`, which is what the translation tables key on."
                                                            },
                                                            "site_default": {
                                                                "type": "boolean",
                                                                "description": "True for the language the shop is written in. Its text is the original, not a translation."
                                                            }
                                                        }
                                                    },
                                                    "description": "The published languages."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}": {
            "get": {
                "operationId": "get-products-id",
                "summary": "Read one product",
                "description": "Everything the product editor needs in one call: the record, its prices, its images and files, its\ncategories, its characteristics and variants, and the definitions of the custom fields that apply\nto it.\n\nAsk for a variant's id and you get the variant, with `parent_id` set. A parent's `variants` are\nlisted in full, so you rarely need to.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "A parent product or a variant.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "The SKU. Unique within the shop."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The long description, as HTML."
                                                },
                                                "description_type": {
                                                    "type": "string",
                                                    "description": "Which editor the description was written with."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "`-1` when this product does not track stock, which is not the same as `0`."
                                                },
                                                "msrp": {
                                                    "type": "number",
                                                    "description": "The manufacturer's suggested price, shown struck through when the shop is configured to."
                                                },
                                                "gtin": {
                                                    "type": "string",
                                                    "description": "The barcode: EAN, UPC or ISBN. This is what `GET /products/lookup` matches on."
                                                },
                                                "condition": {
                                                    "type": "string",
                                                    "description": "New, used, refurbished. Used by the feeds rather than by the shop itself."
                                                },
                                                "weight": {
                                                    "type": "number",
                                                    "description": "Shipping weight, in `weight_unit`."
                                                },
                                                "weight_unit": {
                                                    "type": "string",
                                                    "description": "`kg`, `g`, `lb` or `oz`."
                                                },
                                                "width": {
                                                    "type": "number",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "height": {
                                                    "type": "number",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "length": {
                                                    "type": "number",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "dimension_unit": {
                                                    "type": "string",
                                                    "description": "`m`, `cm`, `mm`, `ft` or `in`."
                                                },
                                                "min_per_order": {
                                                    "type": "integer",
                                                    "description": "The smallest quantity a customer may order, `0` for no minimum."
                                                },
                                                "max_per_order": {
                                                    "type": "integer",
                                                    "description": "The largest, `0` for no maximum."
                                                },
                                                "sale_start": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp before which the product is not on sale."
                                                },
                                                "sale_end": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp after which it is no longer sold."
                                                },
                                                "page_title": {
                                                    "type": "string",
                                                    "description": "SEO title, empty to use the name."
                                                },
                                                "meta_description": {
                                                    "type": "string",
                                                    "description": "SEO description."
                                                },
                                                "keywords": {
                                                    "type": "string",
                                                    "description": "SEO keywords."
                                                },
                                                "canonical": {
                                                    "type": "string",
                                                    "description": "A canonical URL, when this page should point at another."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "The address of the product page on the shop."
                                                },
                                                "alias": {
                                                    "type": "string",
                                                    "description": "The slug used in that address."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User group ids, meaningful only when the mode is `groups`."
                                                        }
                                                    },
                                                    "description": "Who may see the product: `mode` (`all`, `none` or `groups`) and `groups`, which are user **group** ids and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                },
                                                "contact": {
                                                    "type": "boolean",
                                                    "description": "Whether this product is enquired about rather than bought."
                                                },
                                                "warehouse_id": {
                                                    "type": "integer",
                                                    "description": "The warehouse holding the stock, `0` when the shop has none."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`main` for a product, `variant` for one of its variants."
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "The parent product when this is a variant, `0` otherwise."
                                                },
                                                "value_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "For a variant, the characteristic values it stands for."
                                                },
                                                "manufacturer_id": {
                                                    "type": "integer",
                                                    "description": "The brand, `0` when unset."
                                                },
                                                "manufacturer_name": {
                                                    "type": "string",
                                                    "description": "Its name, saving a second call."
                                                },
                                                "tax_id": {
                                                    "type": "integer",
                                                    "description": "The tax category, `0` when the product is untaxed."
                                                },
                                                "tax_name": {
                                                    "type": "string",
                                                    "description": "Its name."
                                                },
                                                "tax_rate": {
                                                    "type": "number",
                                                    "description": "The rate as a fraction, so `0.2` is twenty percent."
                                                },
                                                "prices": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "value": {
                                                                "type": "number",
                                                                "description": "Tax excluded, as stored."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer"
                                                            },
                                                            "min_quantity": {
                                                                "type": "integer",
                                                                "description": "From how many items this row applies, which is how quantity breaks are expressed."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who this price is for, in the same shape as the product access."
                                                            },
                                                            "users": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Named customers, empty for everyone."
                                                            },
                                                            "zone_ids": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Zones this price applies in, empty for everywhere."
                                                            },
                                                            "start_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            },
                                                            "end_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every price row, including the restricted ones. A product with none is not sellable."
                                                },
                                                "images": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute, ready to display."
                                                            },
                                                            "ordering": {
                                                                "type": "integer"
                                                            },
                                                            "description": {
                                                                "type": "string",
                                                                "description": "The alt text."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who may see it."
                                                            },
                                                            "free_download": {
                                                                "type": "boolean",
                                                                "description": "Files only; meaningless on an image."
                                                            }
                                                        }
                                                    },
                                                    "description": "In the order the editor shows them; the first is the main image."
                                                },
                                                "files": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute."
                                                            },
                                                            "ordering": {
                                                                "type": "integer"
                                                            },
                                                            "description": {
                                                                "type": "string"
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "description": "Who may download it."
                                                            },
                                                            "free_download": {
                                                                "type": "boolean",
                                                                "description": "Whether it can be downloaded without buying the product."
                                                            }
                                                        }
                                                    },
                                                    "description": "Downloadable files, in the same shape as the images."
                                                },
                                                "categories": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The categories the product is in."
                                                },
                                                "bundle": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "integer",
                                                                "description": "How many of it the bundle contains."
                                                            }
                                                        }
                                                    },
                                                    "description": "The products this one is made of, when it is a bundle."
                                                },
                                                "options": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "integer"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products offered as options alongside this one."
                                                },
                                                "related": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "integer"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products shown as related."
                                                },
                                                "tags": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "CMS tag ids."
                                                },
                                                "characteristics": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The characteristic, such as Size."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Its name."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer",
                                                                            "description": "The value id, which is what a variant refers to."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name, such as `M`."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The values of it this product uses, such as S, M and L."
                                                            }
                                                        }
                                                    },
                                                    "description": "The characteristics this product varies on. Empty when it has no variants."
                                                },
                                                "variants": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The variant is a product in its own right, and this is its id."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "Its own SKU."
                                                            },
                                                            "quantity": {
                                                                "type": "integer",
                                                                "description": "Its own stock. This is the figure to change, not the parent's."
                                                            },
                                                            "published": {
                                                                "type": "boolean"
                                                            },
                                                            "price": {
                                                                "type": [
                                                                    "number",
                                                                    "null"
                                                                ],
                                                                "description": "`null` when the variant has no price of its own and the parent's applies."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "option_id": {
                                                                            "type": "integer",
                                                                            "description": "The characteristic."
                                                                        },
                                                                        "option_name": {
                                                                            "type": "string",
                                                                            "description": "Its name, so the variant can be labelled without a second call."
                                                                        },
                                                                        "value_id": {
                                                                            "type": "integer",
                                                                            "description": "The value."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "Which characteristic values this variant stands for, one per characteristic."
                                                            },
                                                            "images": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer"
                                                                        },
                                                                        "name": {
                                                                            "type": "string"
                                                                        },
                                                                        "path": {
                                                                            "type": "string",
                                                                            "description": "Relative to the upload folder."
                                                                        },
                                                                        "url": {
                                                                            "type": "string",
                                                                            "description": "Absolute."
                                                                        },
                                                                        "ordering": {
                                                                            "type": "integer"
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The variant's own images, in the same shape as the product's."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every variant, with its own code, stock, price and images. Empty for a product that does not vary."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key used in `custom_fields`."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "`text`, `radio`, `singledropdown`, `file`, and the rest of HikaShop's field types."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type, before it is mapped to something a client can render."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save the product without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object"
                                                                },
                                                                "description": "The choices, for a field that has them. Empty for a free text one."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one choice may be selected."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated, which is what the translation routes offer."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts, comma separated. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The definitions of the custom fields that apply to this product, so a client can build a form for them."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys are whatever this shop has configured; `fields` in the same response says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For custom fields holding a file, the file behind each value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-products-id",
                "summary": "Update a product",
                "description": "Changes the fields you send and leaves the rest alone, which is the opposite of the price and\ncategory calls: this one merges.\n\nSending nothing to change is refused rather than treated as a success, so a client cannot believe\nit saved something it did not.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product or variant.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The same fields as `POST /products`, all of them optional here. A field you do not send keeps its\nvalue; `access` and `custom_fields` are accepted too.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "The SKU. Unique within the shop."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The long description, as HTML."
                                                },
                                                "description_type": {
                                                    "type": "string",
                                                    "description": "Which editor the description was written with."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "`-1` when this product does not track stock, which is not the same as `0`."
                                                },
                                                "msrp": {
                                                    "type": "integer",
                                                    "description": "The manufacturer's suggested price, shown struck through when the shop is configured to."
                                                },
                                                "gtin": {
                                                    "type": "string",
                                                    "description": "The barcode: EAN, UPC or ISBN. This is what `GET /products/lookup` matches on."
                                                },
                                                "condition": {
                                                    "type": "string",
                                                    "description": "New, used, refurbished. Used by the feeds rather than by the shop itself."
                                                },
                                                "weight": {
                                                    "type": "number",
                                                    "description": "Shipping weight, in `weight_unit`."
                                                },
                                                "weight_unit": {
                                                    "type": "string",
                                                    "description": "`kg`, `g`, `lb` or `oz`."
                                                },
                                                "width": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "height": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "length": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "dimension_unit": {
                                                    "type": "string",
                                                    "description": "`m`, `cm`, `mm`, `ft` or `in`."
                                                },
                                                "min_per_order": {
                                                    "type": "integer",
                                                    "description": "The smallest quantity a customer may order, `0` for no minimum."
                                                },
                                                "max_per_order": {
                                                    "type": "integer",
                                                    "description": "The largest, `0` for no maximum."
                                                },
                                                "sale_start": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp before which the product is not on sale."
                                                },
                                                "sale_end": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp after which it is no longer sold."
                                                },
                                                "page_title": {
                                                    "type": "string",
                                                    "description": "SEO title, empty to use the name."
                                                },
                                                "meta_description": {
                                                    "type": "string",
                                                    "description": "SEO description."
                                                },
                                                "keywords": {
                                                    "type": "string",
                                                    "description": "SEO keywords."
                                                },
                                                "canonical": {
                                                    "type": "string",
                                                    "description": "A canonical URL, when this page should point at another."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "The address of the product page on the shop."
                                                },
                                                "alias": {
                                                    "type": "string",
                                                    "description": "The slug used in that address."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User group ids, meaningful only when the mode is `groups`."
                                                        }
                                                    },
                                                    "description": "Who may see the product: `mode` (`all`, `none` or `groups`) and `groups`, which are user **group** ids and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                },
                                                "contact": {
                                                    "type": "boolean",
                                                    "description": "Whether this product is enquired about rather than bought."
                                                },
                                                "warehouse_id": {
                                                    "type": "integer",
                                                    "description": "The warehouse holding the stock, `0` when the shop has none."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`main` for a product, `variant` for one of its variants."
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "The parent product when this is a variant, `0` otherwise."
                                                },
                                                "value_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "For a variant, the characteristic values it stands for."
                                                },
                                                "manufacturer_id": {
                                                    "type": "integer",
                                                    "description": "The brand, `0` when unset."
                                                },
                                                "manufacturer_name": {
                                                    "type": "string",
                                                    "description": "Its name, saving a second call."
                                                },
                                                "tax_id": {
                                                    "type": "integer",
                                                    "description": "The tax category, `0` when the product is untaxed."
                                                },
                                                "tax_name": {
                                                    "type": "string",
                                                    "description": "Its name."
                                                },
                                                "tax_rate": {
                                                    "type": "number",
                                                    "description": "The rate as a fraction, so `0.2` is twenty percent."
                                                },
                                                "prices": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "value": {
                                                                "type": "number",
                                                                "description": "Tax excluded, as stored."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer"
                                                            },
                                                            "min_quantity": {
                                                                "type": "integer",
                                                                "description": "From how many items this row applies, which is how quantity breaks are expressed."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who this price is for, in the same shape as the product access."
                                                            },
                                                            "users": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Named customers, empty for everyone."
                                                            },
                                                            "zone_ids": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Zones this price applies in, empty for everywhere."
                                                            },
                                                            "start_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            },
                                                            "end_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every price row, including the restricted ones. A product with none is not sellable."
                                                },
                                                "images": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute, ready to display."
                                                            },
                                                            "ordering": {
                                                                "type": "integer"
                                                            },
                                                            "description": {
                                                                "type": "string",
                                                                "description": "The alt text."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who may see it."
                                                            },
                                                            "free_download": {
                                                                "type": "boolean",
                                                                "description": "Files only; meaningless on an image."
                                                            }
                                                        }
                                                    },
                                                    "description": "In the order the editor shows them; the first is the main image."
                                                },
                                                "files": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute."
                                                            },
                                                            "ordering": {
                                                                "type": "string"
                                                            },
                                                            "description": {
                                                                "type": "string"
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "description": "Who may download it."
                                                            },
                                                            "free_download": {
                                                                "type": "string",
                                                                "description": "Whether it can be downloaded without buying the product."
                                                            }
                                                        }
                                                    },
                                                    "description": "Downloadable files, in the same shape as the images."
                                                },
                                                "categories": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The categories the product is in."
                                                },
                                                "bundle": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string",
                                                                "description": "How many of it the bundle contains."
                                                            }
                                                        }
                                                    },
                                                    "description": "The products this one is made of, when it is a bundle."
                                                },
                                                "options": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products offered as options alongside this one."
                                                },
                                                "related": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products shown as related."
                                                },
                                                "tags": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "CMS tag ids."
                                                },
                                                "characteristics": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The characteristic, such as Size."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Its name."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer",
                                                                            "description": "The value id, which is what a variant refers to."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name, such as `M`."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The values of it this product uses, such as S, M and L."
                                                            }
                                                        }
                                                    },
                                                    "description": "The characteristics this product varies on. Empty when it has no variants."
                                                },
                                                "variants": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The variant is a product in its own right, and this is its id."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "Its own SKU."
                                                            },
                                                            "quantity": {
                                                                "type": "integer",
                                                                "description": "Its own stock. This is the figure to change, not the parent's."
                                                            },
                                                            "published": {
                                                                "type": "boolean"
                                                            },
                                                            "price": {
                                                                "type": [
                                                                    "number",
                                                                    "null"
                                                                ],
                                                                "description": "`null` when the variant has no price of its own and the parent's applies."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "option_id": {
                                                                            "type": "integer",
                                                                            "description": "The characteristic."
                                                                        },
                                                                        "option_name": {
                                                                            "type": "string",
                                                                            "description": "Its name, so the variant can be labelled without a second call."
                                                                        },
                                                                        "value_id": {
                                                                            "type": "integer",
                                                                            "description": "The value."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "Which characteristic values this variant stands for, one per characteristic."
                                                            },
                                                            "images": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer"
                                                                        },
                                                                        "name": {
                                                                            "type": "string"
                                                                        },
                                                                        "path": {
                                                                            "type": "string",
                                                                            "description": "Relative to the upload folder."
                                                                        },
                                                                        "url": {
                                                                            "type": "string",
                                                                            "description": "Absolute."
                                                                        },
                                                                        "ordering": {
                                                                            "type": "integer"
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The variant's own images, in the same shape as the product's."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every variant, with its own code, stock, price and images. Empty for a product that does not vary."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key used in `custom_fields`."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "`text`, `radio`, `singledropdown`, `file`, and the rest of HikaShop's field types."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type, before it is mapped to something a client can render."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save the product without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object"
                                                                },
                                                                "description": "The choices, for a field that has them. Empty for a free text one."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one choice may be selected."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated, which is what the translation routes offer."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts, comma separated. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The definitions of the custom fields that apply to this product, so a client can build a form for them."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For custom fields holding a file, the file behind each value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: One of your own fields was rejected by its own rules. nothing: The body held no field this shop knows, so nothing would have been written.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-products-id",
                "summary": "Delete a product",
                "description": "Deletes a product and its variants.\n\nOrders that already contain it are untouched: an order line records what was sold at the time, and\nit does not stop meaning something because the catalogue changed.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The product that was deleted."
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "True when the row is gone."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not delete it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "delete_failed: The shop refused to delete it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/lookup": {
            "get": {
                "operationId": "get-products-lookup",
                "summary": "Resolve a scanned barcode",
                "description": "One product from one barcode, for a scanner. It matches the product code and the GTIN, and it\nlooks at variants as well as parents, because the thing with a barcode on it is usually the\nvariant.\n\nExactly one product comes back, or `not_found`. It is deliberately not a search: a scanner needs an\nanswer, not a list.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "barcode",
                        "in": "query",
                        "required": true,
                        "description": "What the scanner read. Matched against the product code and the GTIN.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The product to open. For a variant, this is its parent."
                                                },
                                                "variant_id": {
                                                    "type": "integer",
                                                    "description": "The variant that was scanned, `0` when the barcode belonged to the parent."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "The SKU that matched."
                                                },
                                                "gtin": {
                                                    "type": "string",
                                                    "description": "The barcode held on the record, which may differ in leading zeros from what was scanned."
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "The stock of whichever record matched, so a stock take needs no second call."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "missing_barcode: No barcode was given.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: Nothing in the shop carries that code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/low-stock": {
            "get": {
                "operationId": "get-products-low-stock",
                "summary": "Products running out",
                "description": "Sellable items at or below a stock threshold, cheapest first to reorder. Variants are listed in\ntheir own right, since that is where the stock actually sits.\n\nProducts that do not track stock are left out: they are not running out of anything.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "threshold",
                        "in": "query",
                        "required": false,
                        "description": "At or below which a product counts as low. Defaults to `5`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Defaults to `20`, capped at `100`.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "The parent product."
                                                    },
                                                    "variant_id": {
                                                        "type": "integer",
                                                        "description": "The variant that is low, `0` when the parent itself is."
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The SKU of whichever record is low."
                                                    },
                                                    "quantity": {
                                                        "type": "integer",
                                                        "description": "What is left."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/stock": {
            "post": {
                "operationId": "post-products-id-stock",
                "summary": "Set a product's stock",
                "description": "Sets the tracked quantity to an absolute figure, which is what a stock take does. It is not an\nadjustment: send what the shelf holds, not the difference.\n\nA product with variants keeps no stock of its own, so set it on the variant instead. Asking to set\nit on the parent is refused rather than silently ignored.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product or variant to set.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "quantity": {
                                        "type": "integer",
                                        "description": "The new absolute quantity. `-1` turns stock tracking off for this product."
                                    }
                                },
                                "required": [
                                    "quantity"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "As stored, so you can confirm what was written."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "has_variants: It is a parent: set the stock on one of its variants.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/customers": {
            "get": {
                "operationId": "get-customers",
                "summary": "List customers",
                "description": "The customers the operator may see, with enough to recognise one and to know whether they have\nbought anything.\n\nGuests are included. A shop that lets people order without an account still has a row for each of\nthem, and `type` is how you tell the two apart.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "start",
                        "in": "query",
                        "required": false,
                        "description": "Offset. Defaults to `0`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Defaults to `20`, capped at `100`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Matches the email address, the account name and login, and the first name and surname on any of their addresses, including the two together, so `John Doe` finds a guest who has never had an account.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "The HikaShop customer id, which is not the CMS user id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "The account name, or for a guest the name on their default address, since a guest has no account to take one from."
                                                    },
                                                    "email": {
                                                        "type": "string"
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`registered` for an account, `guest` for someone who ordered without one."
                                                    },
                                                    "created": {
                                                        "type": "integer",
                                                        "description": "Unix timestamp of the first time the shop saw them."
                                                    },
                                                    "order_count": {
                                                        "type": "integer",
                                                        "description": "How many orders they have placed, so a list can be sorted by worth without a second call."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "start": {
                                                    "type": "integer",
                                                    "description": "Echoes the offset used."
                                                },
                                                "limit": {
                                                    "type": "integer",
                                                    "description": "Echoes the page size used."
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Customers matching the filter, before paging."
                                                }
                                            }
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "post-customers",
                "summary": "Create a customer",
                "description": "Creates a customer from an email address and a name, as a guest: no account, no password, nothing\nfor them to log in with.\n\n`POST /customers/{id}/account` turns one into a registered customer afterwards.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "email": {
                                        "type": "string",
                                        "description": "Must not belong to another customer."
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Their display name."
                                    }
                                },
                                "required": [
                                    "email"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The customer that was created."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "email_taken: Another customer already has that address.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The shop refused to save it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/discounts": {
            "get": {
                "operationId": "get-discounts",
                "summary": "List discounts and coupons",
                "description": "Both kinds of reduction live in one table and are told apart by `type`: a **discount** applies by\nitself when its conditions are met, a **coupon** waits for its code to be entered.\n\nThe restriction fields are the interesting part, and they are all lists of ids: which products,\nwhich categories, which zones, which customers, and the same again for exclusions. An empty list\nmeans no restriction of that kind rather than none allowed.",
                "tags": [
                    "discounts"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "start",
                        "in": "query",
                        "required": false,
                        "description": "Offset. Defaults to `0`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Defaults to `20`, capped at `100`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "required": false,
                        "description": "`discount` or `coupon`, to list one kind.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Matches the code.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`discount` applies by itself, `coupon` waits for its code."
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "What the customer types. Empty on a discount."
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "description": "Whether the value is a percentage or a fixed amount."
                                                    },
                                                    "value": {
                                                        "type": "number",
                                                        "description": "The reduction, read according to `kind`."
                                                    },
                                                    "currency_id": {
                                                        "type": "integer",
                                                        "description": "The currency a fixed amount is in."
                                                    },
                                                    "published": {
                                                        "type": "boolean"
                                                    },
                                                    "start": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Unix timestamp before which it does not apply."
                                                    },
                                                    "end": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Unix timestamp after which it expires."
                                                    },
                                                    "minimum_order": {
                                                        "type": "number",
                                                        "description": "Order total below which it does not apply, `0` for none."
                                                    },
                                                    "maximum_order": {
                                                        "type": "number",
                                                        "description": "Order total above which it stops applying, `0` for none."
                                                    },
                                                    "quota": {
                                                        "type": "integer",
                                                        "description": "How many times it may be used in total, `0` for no limit."
                                                    },
                                                    "quota_per_user": {
                                                        "type": "integer",
                                                        "description": "How many times one customer may use it, `0` for no limit."
                                                    },
                                                    "used_times": {
                                                        "type": "integer",
                                                        "description": "How many times it already has been."
                                                    },
                                                    "tax_included": {
                                                        "type": "boolean",
                                                        "description": "Whether the value is understood as tax included."
                                                    },
                                                    "tax_id": {
                                                        "type": "integer",
                                                        "description": "The tax category of the reduction itself."
                                                    },
                                                    "shipping_percent": {
                                                        "type": "number",
                                                        "description": "A reduction on the shipping rather than on the goods."
                                                    },
                                                    "minimum_products": {
                                                        "type": "integer",
                                                        "description": "Fewest items in the cart for it to apply."
                                                    },
                                                    "maximum_products": {
                                                        "type": "integer",
                                                        "description": "Most items for it to still apply."
                                                    },
                                                    "product_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Restricted to these products. Empty means all of them."
                                                    },
                                                    "exclude_product_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Never applies to these."
                                                    },
                                                    "category_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Restricted to these categories."
                                                    },
                                                    "category_childs": {
                                                        "type": "boolean",
                                                        "description": "Whether those categories include their sub-categories."
                                                    },
                                                    "exclude_category_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Never applies in these categories."
                                                    },
                                                    "exclude_category_childs": {
                                                        "type": "boolean",
                                                        "description": "Whether those exclusions include sub-categories."
                                                    },
                                                    "zone_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Restricted to these zones."
                                                    },
                                                    "user_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Restricted to these customers."
                                                    },
                                                    "access": {
                                                        "type": "object",
                                                        "properties": {
                                                            "mode": {
                                                                "type": "string",
                                                                "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                            },
                                                            "groups": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                            }
                                                        },
                                                        "description": "Which user groups it is for, in the usual `mode` and `groups` shape."
                                                    },
                                                    "exclude_access": {
                                                        "type": "object",
                                                        "properties": {
                                                            "mode": {
                                                                "type": "string",
                                                                "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                            },
                                                            "groups": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                            }
                                                        },
                                                        "description": "Which user groups it is never for."
                                                    },
                                                    "auto_load": {
                                                        "type": "boolean",
                                                        "description": "For a coupon, whether the shop applies it without the customer typing it."
                                                    },
                                                    "product_only": {
                                                        "type": "boolean",
                                                        "description": "Whether it reduces only the goods and leaves the fees alone."
                                                    },
                                                    "discounted_products": {
                                                        "type": "integer",
                                                        "description": "How many products in the cart it applied to, on a discount that has been used."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "start": {
                                                    "type": "integer",
                                                    "description": "Echoes the offset used."
                                                },
                                                "limit": {
                                                    "type": "integer",
                                                    "description": "Echoes the page size used."
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Rows matching the filter, before paging."
                                                }
                                            }
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "post-discounts",
                "summary": "Create a discount or a coupon",
                "description": "Creates a reduction and answers with it as the shop stored it.\n\n`type` decides which kind it is: a `coupon` needs a `code`, a `discount` applies by itself. Either\nway `value` is required, read according to `kind`.",
                "tags": [
                    "discounts"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Any field of a discount. `type` and `value` are required, and a coupon also needs a `code`. The restriction lists take ids, and an empty list means no restriction of that kind.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`discount` applies by itself, `coupon` waits for its code."
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "What the customer types. Empty on a discount."
                                                },
                                                "kind": {
                                                    "type": "string",
                                                    "description": "Whether the value is a percentage or a fixed amount."
                                                },
                                                "value": {
                                                    "type": "number",
                                                    "description": "The reduction, read according to `kind`."
                                                },
                                                "currency_id": {
                                                    "type": "integer",
                                                    "description": "The currency a fixed amount is in."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "start": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp before which it does not apply."
                                                },
                                                "end": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp after which it expires."
                                                },
                                                "minimum_order": {
                                                    "type": "number",
                                                    "description": "Order total below which it does not apply, `0` for none."
                                                },
                                                "maximum_order": {
                                                    "type": "number",
                                                    "description": "Order total above which it stops applying, `0` for none."
                                                },
                                                "quota": {
                                                    "type": "integer",
                                                    "description": "How many times it may be used in total, `0` for no limit."
                                                },
                                                "quota_per_user": {
                                                    "type": "integer",
                                                    "description": "How many times one customer may use it, `0` for no limit."
                                                },
                                                "used_times": {
                                                    "type": "integer",
                                                    "description": "How many times it already has been."
                                                },
                                                "tax_included": {
                                                    "type": "boolean",
                                                    "description": "Whether the value is understood as tax included."
                                                },
                                                "tax_id": {
                                                    "type": "integer",
                                                    "description": "The tax category of the reduction itself."
                                                },
                                                "shipping_percent": {
                                                    "type": "number",
                                                    "description": "A reduction on the shipping rather than on the goods."
                                                },
                                                "minimum_products": {
                                                    "type": "integer",
                                                    "description": "Fewest items in the cart for it to apply."
                                                },
                                                "maximum_products": {
                                                    "type": "integer",
                                                    "description": "Most items for it to still apply."
                                                },
                                                "product_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these products. Empty means all of them."
                                                },
                                                "exclude_product_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Never applies to these."
                                                },
                                                "category_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these categories."
                                                },
                                                "category_childs": {
                                                    "type": "boolean",
                                                    "description": "Whether those categories include their sub-categories."
                                                },
                                                "exclude_category_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Never applies in these categories."
                                                },
                                                "exclude_category_childs": {
                                                    "type": "boolean",
                                                    "description": "Whether those exclusions include sub-categories."
                                                },
                                                "zone_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these zones."
                                                },
                                                "user_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these customers."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Which user groups it is for, in the usual `mode` and `groups` shape."
                                                },
                                                "exclude_access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Which user groups it is never for."
                                                },
                                                "auto_load": {
                                                    "type": "boolean",
                                                    "description": "For a coupon, whether the shop applies it without the customer typing it."
                                                },
                                                "product_only": {
                                                    "type": "boolean",
                                                    "description": "Whether it reduces only the goods and leaves the fees alone."
                                                },
                                                "discounted_products": {
                                                    "type": "integer",
                                                    "description": "How many products in the cart it applied to, on a discount that has been used."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "code_required: A coupon needs a code. code_taken: Another coupon already uses that code. value_required: A reduction needs a value.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: Not reachable when creating: the same handler serves the update, where it means no such discount.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The shop refused to save it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/categories": {
            "get": {
                "operationId": "get-categories",
                "summary": "The category tree",
                "description": "One level of the category tree at a time, unpublished categories included, which is what makes this\na management view rather than a shop one.\n\nPass a `parent_id` to walk down. `has_children` tells you whether there is anything below without\nasking, so a tree can be drawn lazily.\n\nHikaShop keeps its manufacturers and its tax categories in the same table as the product\ncategories, told apart by their root. Ask for the tree you want.",
                "tags": [
                    "categories"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "parent_id",
                        "in": "query",
                        "required": false,
                        "description": "Whose children to list. Omit for the top level.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "start",
                        "in": "query",
                        "required": false,
                        "description": "Offset. Defaults to `0`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Defaults to `20`, capped at `100`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Matches the name, across the whole tree rather than one level.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "parent_id": {
                                                        "type": "integer",
                                                        "description": "Its parent, so a flat answer can be rebuilt into a tree."
                                                    },
                                                    "published": {
                                                        "type": "boolean"
                                                    },
                                                    "has_children": {
                                                        "type": "boolean",
                                                        "description": "Whether anything sits below it."
                                                    },
                                                    "image": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Absolute URL of its image, `null` when it has none."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Categories matching, before paging."
                                                },
                                                "start": {
                                                    "type": "integer",
                                                    "description": "Echoes the offset used."
                                                },
                                                "limit": {
                                                    "type": "integer",
                                                    "description": "Echoes the page size used."
                                                }
                                            }
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/categories/{id}": {
            "get": {
                "operationId": "get-categories-id",
                "summary": "Read one category",
                "description": "A category with its description, its image, who may see it, and your own category fields.",
                "tags": [
                    "categories"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The category id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own category fields."
                                                },
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "Its parent."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "Which tree it belongs to: `product`, `manufacturer`, `tax`, and so on."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The long description, as HTML."
                                                },
                                                "meta_description": {
                                                    "type": "string",
                                                    "description": "SEO description."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Who may see it."
                                                },
                                                "image": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Absolute URL of its image, `null` when it has none."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-categories-id",
                "summary": "Update a category",
                "description": "Changes the fields you send and leaves the rest alone. It serves manufacturers and the other trees\nas well, since they are all categories.",
                "tags": [
                    "categories"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The category.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Any of `name`, `parent_id`, `published`, `description`, `meta_description`, `access` and `custom_fields`. What you do not send keeps its value.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string"
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key its value is stored under."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "What to render: `text`, `radio`, `singledropdown`, `file`, and the rest."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save without it."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "What to send back when this choice is picked."
                                                                        },
                                                                        "label": {
                                                                            "type": "string",
                                                                            "description": "What to show."
                                                                        },
                                                                        "label_key": {
                                                                            "type": "string",
                                                                            "description": "The translation key behind the label, when there is one."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The choices, for a field that has them."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one may be chosen."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The definitions of your own category fields."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "Its parent."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "Which tree it belongs to: `product`, `manufacturer`, `tax`, and so on."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The long description, as HTML."
                                                },
                                                "meta_description": {
                                                    "type": "string",
                                                    "description": "SEO description."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Who may see it."
                                                },
                                                "image": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Absolute URL of its image, `null` when it has none."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such category, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: One of your own fields was rejected by its own rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-categories-id",
                "summary": "Delete a category",
                "description": "Deletes a category. The products in it are not deleted; they simply stop being in it, and a product\nleft in no category at all disappears from the shop's listings.",
                "tags": [
                    "categories"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The category.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The category that was deleted."
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "True when the row is gone."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such category, or the operator may not delete it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/massactions": {
            "get": {
                "operationId": "get-massactions",
                "summary": "The shop's own bulk operations",
                "description": "The mass actions the merchant has configured for a listing, so a client can offer the merchant's own\nbulk operations rather than a fixed set of its own.\n\nWhatever they built in the backend appears here, and running one is `POST /massactions/{id}`.",
                "tags": [
                    "massactions"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "table",
                        "in": "query",
                        "required": true,
                        "description": "Which listing: `product`, `order`, `user`, `category`, `address`.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "What to run."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "As the merchant named it."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Their own note about what it does, when they wrote one."
                                                    },
                                                    "table": {
                                                        "type": "string",
                                                        "description": "The listing it belongs to."
                                                    },
                                                    "restricted": {
                                                        "type": "boolean",
                                                        "description": "Whether it may only run on a selection rather than on everything matching a filter."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request: The table is not one the shop has mass actions for.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "forbidden: The operator may not view that kind of record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/media/browse": {
            "get": {
                "operationId": "get-media-browse",
                "summary": "Browse the upload folder",
                "description": "Folders and images inside the shop's upload folder, so an existing image can be picked instead of\nuploaded again.\n\nPaths are relative to that folder and never escape it: a path pointing outside is refused rather\nthan resolved.",
                "tags": [
                    "media"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "folder",
                        "in": "query",
                        "required": false,
                        "description": "Which folder to list, relative to the upload folder. Omit for its root.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "required": false,
                        "description": "Offset into the images, for a folder with many.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "folder": {
                                                    "type": "string",
                                                    "description": "The folder being listed."
                                                },
                                                "parent": {
                                                    "type": "string",
                                                    "description": "The folder above, for walking back up."
                                                },
                                                "has_parent": {
                                                    "type": "boolean",
                                                    "description": "False at the root, where there is nothing above."
                                                },
                                                "folders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The folders inside it."
                                                },
                                                "images": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "name": {
                                                                "type": "string",
                                                                "description": "The file name."
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder, which is what a product image stores."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute, ready to display."
                                                            }
                                                        }
                                                    },
                                                    "description": "The images inside it."
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "How many images the folder holds in all."
                                                },
                                                "offset": {
                                                    "type": "integer",
                                                    "description": "Echoes the offset used."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such folder, or a path that tried to leave the upload folder.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/zones": {
            "get": {
                "operationId": "get-zones",
                "summary": "Search countries, states and zones",
                "description": "The shop's zones, which are its countries, its states and any grouping the merchant made of them.\nMeant for filling a picker: search for a name, or resolve ids you already hold.\n\nAn address stores a zone by its namekey rather than its id, which is why both come back.",
                "tags": [
                    "zones"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Matches the name.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "ids",
                        "in": "query",
                        "required": false,
                        "description": "Comma separated zone ids, to resolve a known set.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "required": false,
                        "description": "Restrict to `country`, `state` or a zone group.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "namekey": {
                                                        "type": "string",
                                                        "description": "What an address stores, such as `FRA` or `US-CA`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Translated where the shop has a translation for it."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`country`, `state`, or the kind of grouping it is."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/users": {
            "get": {
                "operationId": "get-users",
                "summary": "Search customers for a picker",
                "description": "A short list of customers matching a search, for the pickers that restrict a price or a discount to\nnamed people. `GET /customers` is the listing to use for anything else.",
                "tags": [
                    "users"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Matches the name and the email address.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "ids",
                        "in": "query",
                        "required": false,
                        "description": "Comma separated ids, to resolve a known set.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "The customer id, which is what a restriction stores."
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "description": "Enough to tell two people of the same name apart."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/meta": {
            "get": {
                "operationId": "get-products-meta",
                "summary": "Reference data for the product editor",
                "description": "Everything a product form needs to offer choices: the currencies with their formatting, the tax\ncategories, the characteristics and their values, the units, the field definitions, the warehouses\nand the tags.\n\nOne call rather than eight, and it changes rarely, so cache it.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "currencies": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "What a price stores."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "The ISO code, such as `EUR`."
                                                            },
                                                            "symbol": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "decimals": {
                                                                "type": "integer",
                                                                "description": "How many decimal places to show."
                                                            },
                                                            "decimal_sep": {
                                                                "type": "string",
                                                                "description": "The decimal separator."
                                                            },
                                                            "thousands_sep": {
                                                                "type": "string",
                                                                "description": "The thousands separator."
                                                            },
                                                            "symbol_before": {
                                                                "type": "boolean",
                                                                "description": "Whether the symbol goes before the figure."
                                                            },
                                                            "space": {
                                                                "type": "boolean",
                                                                "description": "Whether a space separates the symbol from the figure."
                                                            },
                                                            "rounding_increment": {
                                                                "type": "number",
                                                                "description": "What amounts are rounded to, for a currency without small coins."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every published currency, with enough to format an amount the way the shop does."
                                                },
                                                "main_currency_id": {
                                                    "type": "integer",
                                                    "description": "The shop's own currency."
                                                },
                                                "tax_categories": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "What `tax_id` on a product stores."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "parent_id": {
                                                                "type": "integer",
                                                                "description": "They live in the category tree, so they have a parent like anything else there."
                                                            }
                                                        }
                                                    },
                                                    "description": "The tax categories a product can be put in."
                                                },
                                                "characteristics": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer",
                                                                            "description": "What a variant refers to."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name, such as `M`."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "Its values."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every characteristic in the shop, with its values, for building variants."
                                                },
                                                "weight_units": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "The weight units the shop accepts, such as `kg`."
                                                },
                                                "dimension_units": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "The dimension units the shop accepts, such as `m`."
                                                },
                                                "product_fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key its value is stored under."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "What to render: `text`, `radio`, `singledropdown`, `file`, and the rest."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "What to send back when this choice is picked."
                                                                        },
                                                                        "label": {
                                                                            "type": "string",
                                                                            "description": "What to show."
                                                                        },
                                                                        "label_key": {
                                                                            "type": "string",
                                                                            "description": "The translation key behind the label, when there is one."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The choices, for a field that has them."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one may be chosen."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The definitions of your own product fields."
                                                },
                                                "category_fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key its value is stored under."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "What to render: `text`, `radio`, `singledropdown`, `file`, and the rest."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save without it."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "What to send back when this choice is picked."
                                                                        },
                                                                        "label": {
                                                                            "type": "string",
                                                                            "description": "What to show."
                                                                        },
                                                                        "label_key": {
                                                                            "type": "string",
                                                                            "description": "The translation key behind the label, when there is one."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The choices, for a field that has them."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one may be chosen."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The definitions of your own category fields."
                                                },
                                                "bundle_supported": {
                                                    "type": "boolean",
                                                    "description": "Whether this edition can sell bundles."
                                                },
                                                "warehouses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "What `warehouse_id` on a product stores."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The warehouses stock can be held in. Empty when the shop has none."
                                                },
                                                "tags": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "parent_id": {
                                                                "type": "integer",
                                                                "description": "Tags are a tree in both Joomla and WordPress."
                                                            }
                                                        }
                                                    },
                                                    "description": "The CMS tags a product can carry."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/prices": {
            "put": {
                "operationId": "put-products-id-prices",
                "summary": "Replace a product's prices",
                "description": "Replaces the whole price set, it does not merge into it. Send every price the product should have,\nincluding the ones you are not changing; anything you leave out is deleted.\n\nThat is deliberate, because a price set is a set: quantity breaks and audience restrictions only\nmake sense against each other.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product or variant.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "prices": {
                                        "type": "array",
                                        "items": {
                                            "type": "object"
                                        },
                                        "description": "The complete set. Each needs at least a `value` and a `currency_id`; `min_quantity`, `access`, `users`, `zone_ids`, `start_date` and `end_date` are optional and default to no restriction."
                                    }
                                },
                                "required": [
                                    "prices"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "value": {
                                                        "type": "number",
                                                        "description": "Tax excluded, as stored."
                                                    },
                                                    "currency_id": {
                                                        "type": "integer"
                                                    },
                                                    "min_quantity": {
                                                        "type": "integer",
                                                        "description": "From how many items this row applies, which is how a quantity break is expressed."
                                                    },
                                                    "access": {
                                                        "type": "object",
                                                        "properties": {
                                                            "mode": {
                                                                "type": "string",
                                                                "description": "`all`, `none` or `groups`."
                                                            },
                                                            "groups": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "User group ids, not view levels."
                                                            }
                                                        },
                                                        "description": "Which user groups the price is for."
                                                    },
                                                    "users": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Named customers, empty for everyone."
                                                    },
                                                    "zone_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "integer"
                                                        },
                                                        "description": "Zones it applies in, empty for everywhere."
                                                    },
                                                    "start_date": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Unix timestamp."
                                                    },
                                                    "end_date": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Unix timestamp."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request: No prices array was sent. invalid_price: A price in the set cannot be stored, and the message says which one and why. Nothing is saved: a set is replaced whole or not at all.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/categories": {
            "put": {
                "operationId": "put-products-id-categories",
                "summary": "Replace a product's categories",
                "description": "Replaces the set of categories the product is in. As with the prices, send the complete set: what\nyou leave out is removed.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "categories": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        },
                                        "description": "The complete set of category ids. An empty array takes the product out of every category, which hides it from the shop."
                                    }
                                },
                                "required": [
                                    "categories"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "The category."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Its name, so a client need not look it up."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/translations": {
            "get": {
                "operationId": "get-products-id-translations",
                "summary": "A product's translations",
                "description": "Which of a record's texts can be translated, what they say now in each language, and what the\noriginal says. `enabled` is false on a single-language shop, where there is nothing to do.\n\n`columns` is the list of translatable things: HikaShop's own (the name, the description, the SEO\ntexts) plus every custom field the merchant flagged translatable. It is built the same way the\nbackend builds it, so what you are offered is exactly what the shop will store.\n\nThe labels and values of a custom field itself are website configuration and are not offered here;\nthey belong in the backend.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "enabled": {
                                                    "type": "boolean",
                                                    "description": "False on a single-language shop, where the rest is empty."
                                                },
                                                "languages": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "The tag, such as `fr-FR`."
                                                            },
                                                            "shortcode": {
                                                                "type": "string",
                                                                "description": "The lower-case underscored form the translation tables key on."
                                                            },
                                                            "site_default": {
                                                                "type": "boolean",
                                                                "description": "True for the language the shop is written in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The shop's languages. The default one is marked and comes last, because its text is the original rather than a translation of it."
                                                },
                                                "columns": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "name": {
                                                                "type": "string",
                                                                "description": "The column name, such as `product_name`. This is the key to send a translation under."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "`text` for a line, `textarea` for prose, so a client knows which control to draw."
                                                            }
                                                        }
                                                    },
                                                    "description": "What can be translated on this record: HikaShop's own texts plus every custom field flagged translatable."
                                                },
                                                "values": {
                                                    "type": "object",
                                                    "description": "What each language says now, keyed by language code and then by column. Keyed by language code, and within that by column name, both of which depend on the shop.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "original": {
                                                    "type": "object",
                                                    "description": "What the record itself says, keyed by column, so a translator can see what they are translating. Keyed by column name, which depends on the fields this shop has.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such record, or the operator may not see it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "translation_disabled: This shop does not translate content.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-products-id-translations",
                "summary": "Save a product's translations",
                "description": "Writes the translations of one record. Send only the languages you changed; the rest are left alone.\n\nWhere the shop uses Falang, the values go into its tables. Where it does not, they become language\noverrides keyed on the original text, which is why renaming a product re-keys its translations\nrather than losing them.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "An object keyed by language, each holding an object of column name to text:\n\n`{ \"2\": { \"product_name\": \"Lampe de bureau\", \"product_description\": \"…\" } }`\n\nThe keys are the language ids from `languages` in the GET, and the column names are the ones from\n`columns`. A language you do not send is left alone, and so is a column you do not send within a\nlanguage you do.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The record that was saved."
                                                },
                                                "saved": {
                                                    "type": "integer",
                                                    "description": "How many languages were written, so a client can tell that something was actually stored."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such record, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "translation_disabled: This shop does not translate content.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/categories/{id}/translations": {
            "get": {
                "operationId": "get-categories-id-translations",
                "summary": "A category's translations",
                "description": "The same as for a product, for a category: its name, its description, its SEO texts and its\ntranslatable custom fields.",
                "tags": [
                    "categories"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The category.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "enabled": {
                                                    "type": "boolean",
                                                    "description": "False on a single-language shop, where the rest is empty."
                                                },
                                                "languages": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "The tag, such as `fr-FR`."
                                                            },
                                                            "shortcode": {
                                                                "type": "string",
                                                                "description": "The lower-case underscored form the translation tables key on."
                                                            },
                                                            "site_default": {
                                                                "type": "boolean",
                                                                "description": "True for the language the shop is written in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The shop's languages. The default one is marked and comes last, because its text is the original rather than a translation of it."
                                                },
                                                "columns": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "name": {
                                                                "type": "string",
                                                                "description": "The column name, such as `product_name`. This is the key to send a translation under."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "`text` for a line, `textarea` for prose, so a client knows which control to draw."
                                                            }
                                                        }
                                                    },
                                                    "description": "What can be translated on this record: HikaShop's own texts plus every custom field flagged translatable."
                                                },
                                                "values": {
                                                    "type": "object",
                                                    "description": "What each language says now, keyed by language code and then by column. Keyed by language code, and within that by column name, both of which depend on the shop.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "original": {
                                                    "type": "object",
                                                    "description": "What the record itself says, keyed by column, so a translator can see what they are translating. Keyed by column name, which depends on the fields this shop has.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such record, or the operator may not see it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "translation_disabled: This shop does not translate content.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-categories-id-translations",
                "summary": "Save a category's translations",
                "description": "The same as for a product, for a category.",
                "tags": [
                    "categories"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The category.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "An object keyed by language, each holding an object of column name to text:\n\n`{ \"2\": { \"product_name\": \"Lampe de bureau\", \"product_description\": \"…\" } }`\n\nThe keys are the language ids from `languages` in the GET, and the column names are the ones from\n`columns`. A language you do not send is left alone, and so is a column you do not send within a\nlanguage you do.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The record that was saved."
                                                },
                                                "saved": {
                                                    "type": "integer",
                                                    "description": "How many languages were written."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such record, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "translation_disabled: This shop does not translate content.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/stats/dashboard": {
            "get": {
                "operationId": "get-stats-dashboard",
                "summary": "Dashboard figures",
                "description": "Revenue, orders, average basket and new customers over a period, the same figures again for the\nperiod before it so a change can be shown, the series behind them, and the best sellers.\n\nOnly orders the shop counts as sold are included, so a cancelled order does not inflate a total.\nAmounts are in the shop's own currency.",
                "tags": [
                    "stats"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "range",
                        "in": "query",
                        "required": false,
                        "description": "`day`, `week`, `month` or `year`. Defaults to `month`.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "range": {
                                                    "type": "string",
                                                    "description": "The period the figures cover."
                                                },
                                                "currency_id": {
                                                    "type": "integer",
                                                    "description": "The shop's currency, which every amount here is in."
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "properties": {
                                                        "revenue": {
                                                            "type": "number",
                                                            "description": "Taken in the period."
                                                        },
                                                        "orders": {
                                                            "type": "integer",
                                                            "description": "How many were placed."
                                                        },
                                                        "average_order": {
                                                            "type": "number",
                                                            "description": "Revenue divided by orders."
                                                        },
                                                        "customers": {
                                                            "type": "integer",
                                                            "description": "New customers in the period."
                                                        }
                                                    },
                                                    "description": "The four headline figures."
                                                },
                                                "previous": {
                                                    "type": "object",
                                                    "properties": {
                                                        "revenue": {
                                                            "type": "number",
                                                            "description": "Taken in the preceding period."
                                                        },
                                                        "orders": {
                                                            "type": "integer",
                                                            "description": "Placed in it."
                                                        },
                                                        "average_order": {
                                                            "type": "number",
                                                            "description": "Its average basket."
                                                        },
                                                        "customers": {
                                                            "type": "integer",
                                                            "description": "New customers in it."
                                                        }
                                                    },
                                                    "description": "The same four figures for the preceding period of the same length, for a comparison."
                                                },
                                                "series_granularity": {
                                                    "type": "string",
                                                    "description": "Whether the series is by day, week, month or year, which follows from the range."
                                                },
                                                "revenue_series": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "date": {
                                                                "type": "string",
                                                                "description": "The interval, as a date."
                                                            },
                                                            "revenue": {
                                                                "type": "number",
                                                                "description": "Taken in it."
                                                            }
                                                        }
                                                    },
                                                    "description": "One point per interval, for a chart."
                                                },
                                                "top_products": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "integer",
                                                                "description": "How many were sold."
                                                            }
                                                        }
                                                    },
                                                    "description": "The best sellers of the period."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/groups": {
            "get": {
                "operationId": "get-groups",
                "summary": "The user groups",
                "description": "The CMS user groups, for the pickers that restrict a price, a discount or a product to some of\nthem. The list is the same shape on Joomla and on WordPress, which is the point of it: a client does\nnot need to know which it is talking to.\n\nThese are the ids an `access` object holds. They are user groups and not Joomla view levels.",
                "tags": [
                    "groups"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "What an access object stores."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "The name of the group."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/products/precompute": {
            "get": {
                "operationId": "get-orders-id-products-precompute",
                "summary": "Price a product in an order",
                "description": "What a product would cost on this order, before adding it. The order's customer, currency and zone\nall bear on the price, so this asks the shop rather than guessing from the catalogue.\n\nUse it to show a line before it is committed, then `POST /orders/{id}/products` to add it.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "product_id",
                        "in": "query",
                        "required": true,
                        "description": "The product or variant to price.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "quantity",
                        "in": "query",
                        "required": false,
                        "description": "How many, which matters where the product has quantity breaks. Defaults to `1`.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "product_id": {
                                                    "type": "integer",
                                                    "description": "What was priced."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "Its SKU."
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "The quantity the price was worked out for."
                                                },
                                                "price": {
                                                    "type": "number",
                                                    "description": "Unit price, tax excluded, in the order currency."
                                                },
                                                "tax": {
                                                    "type": "number",
                                                    "description": "Tax per unit, worked out for this order rather than in general."
                                                },
                                                "tax_namekeys": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Which tax rates that came from."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order or no such product, or the operator may not see them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/customers/{id}": {
            "get": {
                "operationId": "get-customers-id",
                "summary": "Read one customer",
                "description": "A customer with their addresses, their orders, which groups they are in and your own customer\nfields.\n\n`can_edit_account` and `groups_editable` are worth reading before drawing a form: they say whether\nthis operator may change this particular account at all, so a client can leave the controls out\nrather than offer something that will be refused. A customer can have many addresses and one\ndefault of each kind.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer, or the operator may not see them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-customers-id",
                "summary": "Delete a customer",
                "description": "Removes a customer and their addresses.\n\nA customer with orders is refused, which is what the backend does too: delete their orders first,\nand then the customer.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "True when the row is gone."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer, or the operator may not delete them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "has_orders: They have orders. Delete those first. delete_failed: The shop refused to delete the row.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-customers-id",
                "summary": "Update a customer's profile",
                "description": "Changes the name, the email address, the login, the password, the user groups and your own customer\nfields, and answers with the customer as it now stands.\n\nThe password is written straight into the CMS account and is never returned by anything. Changing\nthe email of a registered customer changes the account they log in with, which is why a clash is\nrefused rather than silently ignored.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "Their display name."
                                    },
                                    "email": {
                                        "type": "string",
                                        "description": "Must not belong to another account."
                                    },
                                    "username": {
                                        "type": "string",
                                        "description": "The login, for a registered customer."
                                    },
                                    "password": {
                                        "type": "string",
                                        "description": "A new password. Send it only when changing it."
                                    },
                                    "groups": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        },
                                        "description": "The user groups they belong to, as ids from `GET /groups`."
                                    },
                                    "custom_fields": {
                                        "type": "object",
                                        "description": "Your own customer fields, keyed by namekey."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_email: The email address is not one. forbidden_target: The operator may not change this particular account, which is how a super user is protected from being edited by staff. username_taken: Another account has that login. email_taken: Another account has that email address. account_save_failed: The CMS refused to save the account. invalid_fields: One of your own fields was rejected by its own rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/customers/{id}/account": {
            "post": {
                "operationId": "post-customers-id-account",
                "summary": "Give a guest an account",
                "description": "Turns a guest into a registered customer, keeping their orders and addresses, and answers with the\ncustomer as it now stands.\n\nThis is the useful direction: someone ordered without an account, then asked for one. Creating the\naccount separately would leave their history behind.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The guest customer.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "username": {
                                        "type": "string",
                                        "description": "The login to create."
                                    },
                                    "password": {
                                        "type": "string",
                                        "description": "Their password. Never returned by anything afterwards."
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Their display name, defaulting to the one on the guest record."
                                    },
                                    "groups": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        },
                                        "description": "The user groups to put them in."
                                    }
                                },
                                "required": [
                                    "username",
                                    "password"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "already_registered: They already have an account. missing_credentials: A username and a password are both required. invalid_email: The address on the guest record is not usable as an account email. email_taken: Another account has that email address. username_taken: Another account has that login. account_save_failed: The CMS refused to create the account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products": {
            "post": {
                "operationId": "post-products",
                "summary": "Create a product",
                "description": "Creates a product and answers with its id. Only the name is required; everything else can be set\nnow or later with `PUT /products/{id}`.\n\nPrices, images and categories are separate calls, so a new product is not sellable until it has at\nleast one price.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [],
                "security": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Any of the fields a product carries: `name` (required), `code`, `description`, `published`, `msrp`,\n`gtin`, `condition`, `weight`, `weight_unit`, `width`, `height`, `length`, `dimension_unit`,\n`min_per_order`, `max_per_order`, `sale_start`, `sale_end`, `page_title`, `meta_description`,\n`keywords`, `canonical`, `url`, `alias`, `tax_id`, `manufacturer_id`, `contact`, `warehouse_id`,\nplus `access` and `custom_fields`.\n\nThey mean what they mean on `GET /products/{id}`. A field the shop's own schema does not have is\nignored rather than refused, which is what lets one client talk to shops of different vintages.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "The SKU. Unique within the shop."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The long description, as HTML."
                                                },
                                                "description_type": {
                                                    "type": "string",
                                                    "description": "Which editor the description was written with."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "`-1` when this product does not track stock, which is not the same as `0`."
                                                },
                                                "msrp": {
                                                    "type": "integer",
                                                    "description": "The manufacturer's suggested price, shown struck through when the shop is configured to."
                                                },
                                                "gtin": {
                                                    "type": "string",
                                                    "description": "The barcode: EAN, UPC or ISBN. This is what `GET /products/lookup` matches on."
                                                },
                                                "condition": {
                                                    "type": "string",
                                                    "description": "New, used, refurbished. Used by the feeds rather than by the shop itself."
                                                },
                                                "weight": {
                                                    "type": "integer",
                                                    "description": "Shipping weight, in `weight_unit`."
                                                },
                                                "weight_unit": {
                                                    "type": "string",
                                                    "description": "`kg`, `g`, `lb` or `oz`."
                                                },
                                                "width": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "height": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "length": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "dimension_unit": {
                                                    "type": "string",
                                                    "description": "`m`, `cm`, `mm`, `ft` or `in`."
                                                },
                                                "min_per_order": {
                                                    "type": "integer",
                                                    "description": "The smallest quantity a customer may order, `0` for no minimum."
                                                },
                                                "max_per_order": {
                                                    "type": "integer",
                                                    "description": "The largest, `0` for no maximum."
                                                },
                                                "sale_start": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp before which the product is not on sale."
                                                },
                                                "sale_end": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp after which it is no longer sold."
                                                },
                                                "page_title": {
                                                    "type": "string",
                                                    "description": "SEO title, empty to use the name."
                                                },
                                                "meta_description": {
                                                    "type": "string",
                                                    "description": "SEO description."
                                                },
                                                "keywords": {
                                                    "type": "string",
                                                    "description": "SEO keywords."
                                                },
                                                "canonical": {
                                                    "type": "string",
                                                    "description": "A canonical URL, when this page should point at another."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "The address of the product page on the shop."
                                                },
                                                "alias": {
                                                    "type": "string",
                                                    "description": "The slug used in that address."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User group ids, meaningful only when the mode is `groups`."
                                                        }
                                                    },
                                                    "description": "Who may see the product: `mode` (`all`, `none` or `groups`) and `groups`, which are user **group** ids and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                },
                                                "contact": {
                                                    "type": "boolean",
                                                    "description": "Whether this product is enquired about rather than bought."
                                                },
                                                "warehouse_id": {
                                                    "type": "integer",
                                                    "description": "The warehouse holding the stock, `0` when the shop has none."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`main` for a product, `variant` for one of its variants."
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "The parent product when this is a variant, `0` otherwise."
                                                },
                                                "value_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "For a variant, the characteristic values it stands for."
                                                },
                                                "manufacturer_id": {
                                                    "type": "integer",
                                                    "description": "The brand, `0` when unset."
                                                },
                                                "manufacturer_name": {
                                                    "type": "string",
                                                    "description": "Its name, saving a second call."
                                                },
                                                "tax_id": {
                                                    "type": "integer",
                                                    "description": "The tax category, `0` when the product is untaxed."
                                                },
                                                "tax_name": {
                                                    "type": "string",
                                                    "description": "Its name."
                                                },
                                                "tax_rate": {
                                                    "type": "number",
                                                    "description": "The rate as a fraction, so `0.2` is twenty percent."
                                                },
                                                "prices": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "value": {
                                                                "type": "string",
                                                                "description": "Tax excluded, as stored."
                                                            },
                                                            "currency_id": {
                                                                "type": "string"
                                                            },
                                                            "min_quantity": {
                                                                "type": "string",
                                                                "description": "From how many items this row applies, which is how quantity breaks are expressed."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who this price is for, in the same shape as the product access."
                                                            },
                                                            "users": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Named customers, empty for everyone."
                                                            },
                                                            "zone_ids": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Zones this price applies in, empty for everywhere."
                                                            },
                                                            "start_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            },
                                                            "end_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every price row, including the restricted ones. A product with none is not sellable."
                                                },
                                                "images": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute, ready to display."
                                                            },
                                                            "ordering": {
                                                                "type": "string"
                                                            },
                                                            "description": {
                                                                "type": "string",
                                                                "description": "The alt text."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who may see it."
                                                            },
                                                            "free_download": {
                                                                "type": "string",
                                                                "description": "Files only; meaningless on an image."
                                                            }
                                                        }
                                                    },
                                                    "description": "In the order the editor shows them; the first is the main image."
                                                },
                                                "files": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute."
                                                            },
                                                            "ordering": {
                                                                "type": "string"
                                                            },
                                                            "description": {
                                                                "type": "string"
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "description": "Who may download it."
                                                            },
                                                            "free_download": {
                                                                "type": "string",
                                                                "description": "Whether it can be downloaded without buying the product."
                                                            }
                                                        }
                                                    },
                                                    "description": "Downloadable files, in the same shape as the images."
                                                },
                                                "categories": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The categories the product is in."
                                                },
                                                "bundle": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string",
                                                                "description": "How many of it the bundle contains."
                                                            }
                                                        }
                                                    },
                                                    "description": "The products this one is made of, when it is a bundle."
                                                },
                                                "options": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products offered as options alongside this one."
                                                },
                                                "related": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products shown as related."
                                                },
                                                "tags": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "CMS tag ids."
                                                },
                                                "characteristics": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The characteristic, such as Size."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Its name."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer",
                                                                            "description": "The value id, which is what a variant refers to."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name, such as `M`."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The values of it this product uses, such as S, M and L."
                                                            }
                                                        }
                                                    },
                                                    "description": "The characteristics this product varies on. Empty when it has no variants."
                                                },
                                                "variants": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The variant is a product in its own right, and this is its id."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "Its own SKU."
                                                            },
                                                            "quantity": {
                                                                "type": "integer",
                                                                "description": "Its own stock. This is the figure to change, not the parent's."
                                                            },
                                                            "published": {
                                                                "type": "boolean"
                                                            },
                                                            "price": {
                                                                "type": [
                                                                    "number",
                                                                    "null"
                                                                ],
                                                                "description": "`null` when the variant has no price of its own and the parent's applies."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "option_id": {
                                                                            "type": "integer",
                                                                            "description": "The characteristic."
                                                                        },
                                                                        "option_name": {
                                                                            "type": "string",
                                                                            "description": "Its name, so the variant can be labelled without a second call."
                                                                        },
                                                                        "value_id": {
                                                                            "type": "integer",
                                                                            "description": "The value."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "Which characteristic values this variant stands for, one per characteristic."
                                                            },
                                                            "images": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer"
                                                                        },
                                                                        "name": {
                                                                            "type": "string"
                                                                        },
                                                                        "path": {
                                                                            "type": "string",
                                                                            "description": "Relative to the upload folder."
                                                                        },
                                                                        "url": {
                                                                            "type": "string",
                                                                            "description": "Absolute."
                                                                        },
                                                                        "ordering": {
                                                                            "type": "integer"
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The variant's own images, in the same shape as the product's."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every variant, with its own code, stock, price and images. Empty for a product that does not vary."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key used in `custom_fields`."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "`text`, `radio`, `singledropdown`, `file`, and the rest of HikaShop's field types."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type, before it is mapped to something a client can render."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save the product without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object"
                                                                },
                                                                "description": "The choices, for a field that has them. Empty for a free text one."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one choice may be selected."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated, which is what the translation routes offer."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts, comma separated. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The definitions of the custom fields that apply to this product, so a client can build a form for them."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For custom fields holding a file, the file behind each value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: One of your own fields was rejected by its own rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The shop refused to save the product.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "get": {
                "operationId": "get-products",
                "summary": "List products",
                "description": "The catalogue as the backend sees it, unpublished products included, which is what makes this\ndifferent from the front end.\n\nVariants are not listed on their own. A parent carries `has_variants`, and\n`GET /products/{id}` returns the variants themselves.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "start",
                        "in": "query",
                        "required": false,
                        "description": "Offset into the result set. Defaults to `0`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Page size. Defaults to `20` and is capped at `100`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Matches the product name and the product code.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "ids",
                        "in": "query",
                        "required": false,
                        "description": "Comma separated product ids, to resolve a known set in one call.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "category_id",
                        "in": "query",
                        "required": false,
                        "description": "Restrict to one category.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "The SKU. Unique within the shop."
                                                    },
                                                    "quantity": {
                                                        "type": "integer",
                                                        "description": "`-1` when the product does not track stock, which is not the same as `0`."
                                                    },
                                                    "published": {
                                                        "type": "boolean"
                                                    },
                                                    "has_variants": {
                                                        "type": "boolean",
                                                        "description": "Ask `GET /products/{id}` for the variants themselves."
                                                    },
                                                    "image": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "Absolute URL of the main image, or `null`."
                                                    },
                                                    "price": {
                                                        "type": [
                                                            "number",
                                                            "null"
                                                        ],
                                                        "description": "`null` when the product has no price row at all."
                                                    },
                                                    "currency_id": {
                                                        "type": "integer",
                                                        "description": "A row in the shop's currency table, not an ISO code."
                                                    },
                                                    "custom_fields": {
                                                        "type": "object",
                                                        "description": "The listing values of this product, keyed by field namekey. The keys are whatever this shop has configured, so there is no list to give. `fields` in the envelope says what they are.",
                                                        "additionalProperties": true,
                                                        "x-open": true
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "start": {
                                                    "type": "integer",
                                                    "description": "Echoes the offset used."
                                                },
                                                "limit": {
                                                    "type": "integer",
                                                    "description": "Echoes the page size used."
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Rows matching the filter, before paging. This is how you know there is another page."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The custom fields shown on listings, so a client can label the values it just received."
                                                }
                                            }
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/variants": {
            "put": {
                "operationId": "put-products-id-variants",
                "summary": "Reconcile the variant set",
                "description": "Takes the variants a product should have and makes the shop agree: it creates the ones that are\nmissing, updates the ones that exist and removes the ones you left out.\n\nA variant is identified by the characteristic values it stands for rather than by an id, because\nthat is what makes it that variant. Send the whole set.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The parent product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "variants": {
                                        "type": "array",
                                        "items": {
                                            "type": "object"
                                        },
                                        "description": "The complete set. Each needs the characteristic `values` it stands for, and may carry `code`, `quantity`, `published` and `price`."
                                    }
                                },
                                "required": [
                                    "variants"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "characteristics": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The characteristics the product now varies on, as they stand after the change."
                                                },
                                                "variants": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The variants as they now stand, in the same shape as on the product."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/variants/{vid}": {
            "put": {
                "operationId": "put-products-id-variants-vid",
                "summary": "Edit one variant",
                "description": "Changes one variant without touching the others, which is what a stock correction or a price change\non a single size needs.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The parent product.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "vid",
                        "in": "path",
                        "required": true,
                        "description": "The variant.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Any of `code`, `quantity`, `published` and `price`, and your own product fields. What you do not send is left alone.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "The SKU. Unique within the shop."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The long description, as HTML."
                                                },
                                                "description_type": {
                                                    "type": "string",
                                                    "description": "Which editor the description was written with."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "`-1` when this product does not track stock, which is not the same as `0`."
                                                },
                                                "msrp": {
                                                    "type": "integer",
                                                    "description": "The manufacturer's suggested price, shown struck through when the shop is configured to."
                                                },
                                                "gtin": {
                                                    "type": "string",
                                                    "description": "The barcode: EAN, UPC or ISBN. This is what `GET /products/lookup` matches on."
                                                },
                                                "condition": {
                                                    "type": "string",
                                                    "description": "New, used, refurbished. Used by the feeds rather than by the shop itself."
                                                },
                                                "weight": {
                                                    "type": "integer",
                                                    "description": "Shipping weight, in `weight_unit`."
                                                },
                                                "weight_unit": {
                                                    "type": "string",
                                                    "description": "`kg`, `g`, `lb` or `oz`."
                                                },
                                                "width": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "height": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "length": {
                                                    "type": "integer",
                                                    "description": "In `dimension_unit`."
                                                },
                                                "dimension_unit": {
                                                    "type": "string",
                                                    "description": "`m`, `cm`, `mm`, `ft` or `in`."
                                                },
                                                "min_per_order": {
                                                    "type": "integer",
                                                    "description": "The smallest quantity a customer may order, `0` for no minimum."
                                                },
                                                "max_per_order": {
                                                    "type": "integer",
                                                    "description": "The largest, `0` for no maximum."
                                                },
                                                "sale_start": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp before which the product is not on sale."
                                                },
                                                "sale_end": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp after which it is no longer sold."
                                                },
                                                "page_title": {
                                                    "type": "string",
                                                    "description": "SEO title, empty to use the name."
                                                },
                                                "meta_description": {
                                                    "type": "string",
                                                    "description": "SEO description."
                                                },
                                                "keywords": {
                                                    "type": "string",
                                                    "description": "SEO keywords."
                                                },
                                                "canonical": {
                                                    "type": "string",
                                                    "description": "A canonical URL, when this page should point at another."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "The address of the product page on the shop."
                                                },
                                                "alias": {
                                                    "type": "string",
                                                    "description": "The slug used in that address."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User group ids, meaningful only when the mode is `groups`."
                                                        }
                                                    },
                                                    "description": "Who may see the product: `mode` (`all`, `none` or `groups`) and `groups`, which are user **group** ids and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                },
                                                "contact": {
                                                    "type": "boolean",
                                                    "description": "Whether this product is enquired about rather than bought."
                                                },
                                                "warehouse_id": {
                                                    "type": "integer",
                                                    "description": "The warehouse holding the stock, `0` when the shop has none."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`main` for a product, `variant` for one of its variants."
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "The parent product when this is a variant, `0` otherwise."
                                                },
                                                "value_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "For a variant, the characteristic values it stands for."
                                                },
                                                "manufacturer_id": {
                                                    "type": "integer",
                                                    "description": "The brand, `0` when unset."
                                                },
                                                "manufacturer_name": {
                                                    "type": "string",
                                                    "description": "Its name, saving a second call."
                                                },
                                                "tax_id": {
                                                    "type": "integer",
                                                    "description": "The tax category, `0` when the product is untaxed."
                                                },
                                                "tax_name": {
                                                    "type": "string",
                                                    "description": "Its name."
                                                },
                                                "tax_rate": {
                                                    "type": "number",
                                                    "description": "The rate as a fraction, so `0.2` is twenty percent."
                                                },
                                                "prices": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "value": {
                                                                "type": "string",
                                                                "description": "Tax excluded, as stored."
                                                            },
                                                            "currency_id": {
                                                                "type": "string"
                                                            },
                                                            "min_quantity": {
                                                                "type": "string",
                                                                "description": "From how many items this row applies, which is how quantity breaks are expressed."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who this price is for, in the same shape as the product access."
                                                            },
                                                            "users": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Named customers, empty for everyone."
                                                            },
                                                            "zone_ids": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "integer"
                                                                },
                                                                "description": "Zones this price applies in, empty for everywhere."
                                                            },
                                                            "start_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            },
                                                            "end_date": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Unix timestamp."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every price row, including the restricted ones. A product with none is not sellable."
                                                },
                                                "images": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute, ready to display."
                                                            },
                                                            "ordering": {
                                                                "type": "integer"
                                                            },
                                                            "description": {
                                                                "type": "string",
                                                                "description": "The alt text."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "As above."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "As above."
                                                                    }
                                                                },
                                                                "description": "Who may see it."
                                                            },
                                                            "free_download": {
                                                                "type": "boolean",
                                                                "description": "Files only; meaningless on an image."
                                                            }
                                                        }
                                                    },
                                                    "description": "In the order the editor shows them; the first is the main image."
                                                },
                                                "files": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute."
                                                            },
                                                            "ordering": {
                                                                "type": "string"
                                                            },
                                                            "description": {
                                                                "type": "string"
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "description": "Who may download it."
                                                            },
                                                            "free_download": {
                                                                "type": "string",
                                                                "description": "Whether it can be downloaded without buying the product."
                                                            }
                                                        }
                                                    },
                                                    "description": "Downloadable files, in the same shape as the images."
                                                },
                                                "categories": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The categories the product is in."
                                                },
                                                "bundle": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string",
                                                                "description": "How many of it the bundle contains."
                                                            }
                                                        }
                                                    },
                                                    "description": "The products this one is made of, when it is a bundle."
                                                },
                                                "options": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products offered as options alongside this one."
                                                },
                                                "related": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "quantity": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "Products shown as related."
                                                },
                                                "tags": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "CMS tag ids."
                                                },
                                                "characteristics": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The characteristic, such as Size."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Its name."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer",
                                                                            "description": "The value id, which is what a variant refers to."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name, such as `M`."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The values of it this product uses, such as S, M and L."
                                                            }
                                                        }
                                                    },
                                                    "description": "The characteristics this product varies on. Empty when it has no variants."
                                                },
                                                "variants": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The variant is a product in its own right, and this is its id."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "Its own SKU."
                                                            },
                                                            "quantity": {
                                                                "type": "integer",
                                                                "description": "Its own stock. This is the figure to change, not the parent's."
                                                            },
                                                            "published": {
                                                                "type": "boolean"
                                                            },
                                                            "price": {
                                                                "type": [
                                                                    "number",
                                                                    "null"
                                                                ],
                                                                "description": "`null` when the variant has no price of its own and the parent's applies."
                                                            },
                                                            "values": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "option_id": {
                                                                            "type": "integer",
                                                                            "description": "The characteristic."
                                                                        },
                                                                        "option_name": {
                                                                            "type": "string",
                                                                            "description": "Its name, so the variant can be labelled without a second call."
                                                                        },
                                                                        "value_id": {
                                                                            "type": "integer",
                                                                            "description": "The value."
                                                                        },
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "Its name."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "Which characteristic values this variant stands for, one per characteristic."
                                                            },
                                                            "images": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "integer"
                                                                        },
                                                                        "name": {
                                                                            "type": "string"
                                                                        },
                                                                        "path": {
                                                                            "type": "string",
                                                                            "description": "Relative to the upload folder."
                                                                        },
                                                                        "url": {
                                                                            "type": "string",
                                                                            "description": "Absolute."
                                                                        },
                                                                        "ordering": {
                                                                            "type": "integer"
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The variant's own images, in the same shape as the product's."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every variant, with its own code, stock, price and images. Empty for a product that does not vary."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key used in `custom_fields`."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "`text`, `radio`, `singledropdown`, `file`, and the rest of HikaShop's field types."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type, before it is mapped to something a client can render."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save the product without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object"
                                                                },
                                                                "description": "The choices, for a field that has them. Empty for a free text one."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one choice may be selected."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated, which is what the translation routes offer."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts, comma separated. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The definitions of the custom fields that apply to this product, so a client can build a form for them."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For custom fields holding a file, the file behind each value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such variant, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: One of your own fields was rejected by its own rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/coupon": {
            "post": {
                "operationId": "post-orders-id-coupon",
                "summary": "Apply a coupon to an order",
                "description": "Applies a coupon by its code and re-totals the order.\n\nThe shop validates it again here against this order: its dates, its quota, its minimum, the\nproducts in the cart and the customer. A coupon that appears in `GET /coupons` can still be refused\nfor this particular order, which is the point of validating rather than trusting the list.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "code": {
                                        "type": "string",
                                        "description": "The coupon code, as the customer would type it."
                                    }
                                },
                                "required": [
                                    "code"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The order."
                                                },
                                                "fees": {
                                                    "type": "object",
                                                    "properties": {
                                                        "discount": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "A positive figure, already subtracted from the total."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "code": {
                                                                    "type": "string",
                                                                    "description": "The coupon code, empty for a discount applied by hand."
                                                                }
                                                            },
                                                            "description": "Its `amount`, its `tax`, the `tax_namekeys` behind that tax, and the coupon `code` when one was used."
                                                        },
                                                        "shipping": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that handled it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The shipping charge and what carried it."
                                                        },
                                                        "payment": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that took it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The payment fee and what took it."
                                                        }
                                                    },
                                                    "description": "The discount, shipping and payment amounts of the order."
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "properties": {
                                                        "total": {
                                                            "type": "number",
                                                            "description": "What the customer owes, tax included."
                                                        },
                                                        "discount": {
                                                            "type": "number",
                                                            "description": "The discount applied, as a positive figure already subtracted."
                                                        },
                                                        "shipping": {
                                                            "type": "number",
                                                            "description": "The shipping charged."
                                                        },
                                                        "payment": {
                                                            "type": "number",
                                                            "description": "The payment fee charged."
                                                        },
                                                        "tax": {
                                                            "type": "number",
                                                            "description": "The tax within the total, not on top of it."
                                                        }
                                                    },
                                                    "description": "The order totalled, so a client need not compute it and disagree with the shop."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_coupon: No such code, or it does not apply to this order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-orders-id-coupon",
                "summary": "Remove the discount from an order",
                "description": "Takes the coupon or the hand-applied discount off the order and re-totals it. There is nothing to\nsend.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The order."
                                                },
                                                "fees": {
                                                    "type": "object",
                                                    "properties": {
                                                        "discount": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "A positive figure, already subtracted from the total."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "code": {
                                                                    "type": "string",
                                                                    "description": "The coupon code, empty for a discount applied by hand."
                                                                }
                                                            },
                                                            "description": "Its `amount`, its `tax`, the `tax_namekeys` behind that tax, and the coupon `code` when one was used."
                                                        },
                                                        "shipping": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that handled it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The shipping charge and what carried it."
                                                        },
                                                        "payment": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that took it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The payment fee and what took it."
                                                        }
                                                    },
                                                    "description": "The discount, shipping and payment amounts of the order."
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "properties": {
                                                        "total": {
                                                            "type": "number",
                                                            "description": "What the customer owes, tax included."
                                                        },
                                                        "discount": {
                                                            "type": "number",
                                                            "description": "The discount applied, as a positive figure already subtracted."
                                                        },
                                                        "shipping": {
                                                            "type": "number",
                                                            "description": "The shipping charged."
                                                        },
                                                        "payment": {
                                                            "type": "number",
                                                            "description": "The payment fee charged."
                                                        },
                                                        "tax": {
                                                            "type": "number",
                                                            "description": "The tax within the total, not on top of it."
                                                        }
                                                    },
                                                    "description": "The order totalled, so a client need not compute it and disagree with the shop."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/products": {
            "post": {
                "operationId": "post-orders-id-products",
                "summary": "Add a line to an order",
                "description": "Adds a product to an existing order and re-totals it.\n\nSend a `price` only to override what the shop would charge; leave it out and the order's own\npricing applies, which is what `GET /orders/{id}/products/precompute` shows you beforehand.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "product_id": {
                                        "type": "integer",
                                        "description": "The product or variant to add."
                                    },
                                    "quantity": {
                                        "type": "integer",
                                        "description": "How many. Defaults to `1`."
                                    },
                                    "price": {
                                        "type": "number",
                                        "description": "Unit price, tax excluded, to override the shop. Omit to let the shop price it."
                                    },
                                    "tax_namekeys": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Which tax rates to apply, when overriding the price. Omit to let the shop decide."
                                    }
                                },
                                "required": [
                                    "product_id"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The order."
                                                },
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The line id, which is what the line routes take. It is not the product id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "The product as it was named when ordered."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "Its SKU at the time."
                                                            },
                                                            "quantity": {
                                                                "type": "integer"
                                                            },
                                                            "price": {
                                                                "type": "number",
                                                                "description": "Unit price, tax excluded, as agreed at the time."
                                                            },
                                                            "tax": {
                                                                "type": "number",
                                                                "description": "Tax on the line."
                                                            },
                                                            "editable": {
                                                                "type": "boolean",
                                                                "description": "False once the line can no longer be changed."
                                                            }
                                                        }
                                                    },
                                                    "description": "The lines as they now stand, in the same shape as on the order."
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "properties": {
                                                        "total": {
                                                            "type": "number",
                                                            "description": "What the customer owes, tax included."
                                                        },
                                                        "discount": {
                                                            "type": "number",
                                                            "description": "The discount applied, as a positive figure already subtracted."
                                                        },
                                                        "shipping": {
                                                            "type": "number",
                                                            "description": "The shipping charged."
                                                        },
                                                        "payment": {
                                                            "type": "number",
                                                            "description": "The payment fee charged."
                                                        },
                                                        "tax": {
                                                            "type": "number",
                                                            "description": "The tax within the total, not on top of it."
                                                        }
                                                    },
                                                    "description": "The order totalled, so a client need not compute it and disagree with the shop."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order or product, or the operator may not change the order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/products/{lineId}": {
            "put": {
                "operationId": "put-orders-id-products-lineid",
                "summary": "Change a line's quantity",
                "description": "Changes how many of one line the order holds, and re-totals it. A quantity of `0` removes the line.\n\nThe id in the path is the **line** id from `items`, not the product id: the same product can appear\non an order more than once.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "lineId",
                        "in": "path",
                        "required": true,
                        "description": "The line, from `items[].id` on the order.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "quantity": {
                                        "type": "integer",
                                        "description": "The new quantity. `0` removes the line."
                                    }
                                },
                                "required": [
                                    "quantity"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The order."
                                                },
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The line id, which is what the line routes take. It is not the product id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "The product as it was named when ordered."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "Its SKU at the time."
                                                            },
                                                            "quantity": {
                                                                "type": "integer"
                                                            },
                                                            "price": {
                                                                "type": "number",
                                                                "description": "Unit price, tax excluded, as agreed at the time."
                                                            },
                                                            "tax": {
                                                                "type": "number",
                                                                "description": "Tax on the line."
                                                            },
                                                            "editable": {
                                                                "type": "boolean",
                                                                "description": "False once the line can no longer be changed."
                                                            }
                                                        }
                                                    },
                                                    "description": "The lines as they now stand."
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "properties": {
                                                        "total": {
                                                            "type": "number",
                                                            "description": "What the customer owes, tax included."
                                                        },
                                                        "discount": {
                                                            "type": "number",
                                                            "description": "The discount applied, as a positive figure already subtracted."
                                                        },
                                                        "shipping": {
                                                            "type": "number",
                                                            "description": "The shipping charged."
                                                        },
                                                        "payment": {
                                                            "type": "number",
                                                            "description": "The payment fee charged."
                                                        },
                                                        "tax": {
                                                            "type": "number",
                                                            "description": "The tax within the total, not on top of it."
                                                        }
                                                    },
                                                    "description": "The order totalled, so a client need not compute it and disagree with the shop."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order or line, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/massactions/{id}": {
            "post": {
                "operationId": "post-massactions-id",
                "summary": "Run a mass action",
                "description": "Runs one of the merchant's own bulk operations over a selection.\n\nIt runs the same code the backend runs, so whatever the action does there it does here, including\nwhatever a third-party plugin added to it. Give it the ids to work on.",
                "tags": [
                    "massactions"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The mass action, from `GET /massactions`.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "ids": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        },
                                        "description": "The records to run it over, from the listing the action belongs to."
                                    }
                                },
                                "required": [
                                    "ids"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "ok": {
                                                    "type": "boolean",
                                                    "description": "Whether the action reported success."
                                                },
                                                "count": {
                                                    "type": "integer",
                                                    "description": "How many records it worked on."
                                                },
                                                "report": {
                                                    "type": "string",
                                                    "description": "Whatever the action had to say, ready to show. Its wording is the action's own."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request: No ids were sent, or the action is not one this shop has.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "forbidden: The operator may not work on that kind of record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders": {
            "post": {
                "operationId": "post-orders",
                "summary": "Create an order by hand",
                "description": "Creates an empty order for a customer, to be filled in with lines, fees and an address.\n\nGive it either an existing `user_id` or a `guest` with at least an email address, which is how an\norder gets taken over the telephone from somebody who has never bought before.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "user_id": {
                                        "type": "integer",
                                        "description": "An existing customer. Give this or `guest`."
                                    },
                                    "guest": {
                                        "type": "object",
                                        "description": "A new guest customer, needing at least `email` and usually a name."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The order that was created, to add lines to."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "no_customer: Neither a user_id nor a usable guest was given.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "get": {
                "operationId": "get-orders",
                "summary": "List orders",
                "description": "The orders the operator may see, newest first. It is the listing the app's order screen is built\non, so it carries just enough to draw a row and no more; ask for one order when you need the rest.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "start",
                        "in": "query",
                        "required": false,
                        "description": "Offset. Defaults to `0`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Defaults to `20`, capped at `100`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Matches the order number and the customer.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "A status namekey, as listed by `GET /statuses`.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "The order id, which is what every other order route takes."
                                                    },
                                                    "number": {
                                                        "type": "string",
                                                        "description": "The order number the customer sees, which is not the id."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "A namekey, not a label. `GET /statuses` translates it."
                                                    },
                                                    "created": {
                                                        "type": "integer",
                                                        "description": "Unix timestamp."
                                                    },
                                                    "total": {
                                                        "type": "number",
                                                        "description": "What the customer owes, tax included, in the order currency."
                                                    },
                                                    "currency_id": {
                                                        "type": "integer",
                                                        "description": "The order keeps the currency it was placed in, which need not be the shop default."
                                                    },
                                                    "customer": {
                                                        "type": "object",
                                                        "properties": {
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "email": {
                                                                "type": "string"
                                                            }
                                                        },
                                                        "description": "Enough to name the buyer in a list."
                                                    },
                                                    "custom_fields": {
                                                        "type": "object",
                                                        "description": "The listing values of your own order fields, keyed by namekey. The keys are whatever this shop has configured; `fields` in the envelope says what they are.",
                                                        "additionalProperties": true,
                                                        "x-open": true
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "start": {
                                                    "type": "integer",
                                                    "description": "Echoes the offset used."
                                                },
                                                "limit": {
                                                    "type": "integer",
                                                    "description": "Echoes the page size used."
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Orders matching the filter, before paging."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions behind `custom_fields`."
                                                }
                                            }
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/fields": {
            "put": {
                "operationId": "put-orders-id-fields",
                "summary": "Save an order's custom fields",
                "description": "Writes the merchant's own order fields. Only the fields you send are touched.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fields": {
                                        "type": "object",
                                        "description": "Keyed by field namekey."
                                    }
                                },
                                "required": [
                                    "fields"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The order."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "The values as they now stand. The keys depend on the shop.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: A field was rejected by its own rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/address/{type}": {
            "put": {
                "operationId": "put-orders-id-address-type",
                "summary": "Save an address of an order",
                "description": "Writes the billing or shipping address of an order, using the fields `GET` gave you.\n\nThe address on an order is its own copy, so changing it here does not change the customer's address\nbook, and vice versa. That is deliberate: an invoice should not change because somebody moved.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "type",
                        "in": "path",
                        "required": true,
                        "description": "`billing` or `shipping`.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fields": {
                                        "type": "object",
                                        "description": "Keyed by address field namekey, the same keys `GET` returned in `values`."
                                    }
                                },
                                "required": [
                                    "fields"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "type": {
                                                    "type": "string",
                                                    "description": "Which address was written."
                                                },
                                                "address_id": {
                                                    "type": "integer",
                                                    "description": "The address row, created if there was none."
                                                },
                                                "values": {
                                                    "type": "object",
                                                    "description": "The values as stored. Keyed by whatever address fields this shop has.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "country_name": {
                                                    "type": "string",
                                                    "description": "The country spelled out."
                                                },
                                                "state_name": {
                                                    "type": "string",
                                                    "description": "The state spelled out, empty where the country has none."
                                                },
                                                "summary": {
                                                    "type": "object",
                                                    "properties": {
                                                        "name": {
                                                            "type": "string"
                                                        },
                                                        "company": {
                                                            "type": "string"
                                                        },
                                                        "formatted": {
                                                            "type": "object",
                                                            "properties": {
                                                                "text": {
                                                                    "type": "string",
                                                                    "description": "Several lines, for an invoice or a label."
                                                                },
                                                                "one_line": {
                                                                    "type": "string",
                                                                    "description": "One line, for a list."
                                                                }
                                                            },
                                                            "description": "Laid out the way this shop lays addresses out, which follows its address format setting."
                                                        },
                                                        "street": {
                                                            "type": "string"
                                                        },
                                                        "city": {
                                                            "type": "string"
                                                        },
                                                        "post_code": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "description": "The address ready to show, without re-reading the order."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: A field was rejected by its own rules. invalid_address: The address is not one the shop will accept, usually a missing required field.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "get": {
                "operationId": "get-orders-id-address-type",
                "summary": "An address of an order, with its form",
                "description": "The billing or shipping address of an order, together with the form the shop would use to edit it.\n\nThe form is sent with the values because a shop decides its own address fields: which exist, which\nare required, and in what order. Build the form from `fields` rather than assuming a shape, and\n`PUT` the same keys back.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order id.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "type",
                        "in": "path",
                        "required": true,
                        "description": "`billing` or `shipping`.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "type": {
                                                    "type": "string",
                                                    "description": "Which address this is."
                                                },
                                                "address_id": {
                                                    "type": "integer",
                                                    "description": "The address row, `0` when the order has none of that kind."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key to send the value back under."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "What to render: `text`, `zone`, `singledropdown`, and the rest."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save the address without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "What to send back when this choice is picked."
                                                                        },
                                                                        "label": {
                                                                            "type": "string",
                                                                            "description": "What to show."
                                                                        },
                                                                        "label_key": {
                                                                            "type": "string",
                                                                            "description": "The translation key behind the label, when there is one."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The choices, for a field that has them. A country or a state is filled from the zones rather than from here."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one may be chosen."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Not meaningful on an address, where values are the customer's own words."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "Unused on an address field."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "Unused on an address field."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The shop's address fields, in display order."
                                                },
                                                "values": {
                                                    "type": "object",
                                                    "description": "The current values, keyed by field namekey. Keyed by whatever address fields this shop has.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "country_name": {
                                                    "type": "string",
                                                    "description": "The country spelled out, since the value itself is a zone id."
                                                },
                                                "state_name": {
                                                    "type": "string",
                                                    "description": "The state spelled out, empty where the country has none."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not see it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/images": {
            "post": {
                "operationId": "post-products-id-images",
                "summary": "Attach an image or a file",
                "description": "Adds an image or a downloadable file to a product, either by sending the bytes or by pointing at\nsomething already in the upload folder.\n\nSend `data` as base64 to upload, or `path` to attach a file that `GET /media/browse` already showed\nyou. The extension is checked against what the shop allows, so a refusal is the shop's policy rather\nthan a fault.\n\nThe same route serves `/images` and `/files`; which one you call decides where it goes.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "The bytes, base64 encoded. Give this or `path`."
                                    },
                                    "path": {
                                        "type": "string",
                                        "description": "A file already in the upload folder, relative to it, as `GET /media/browse` returns."
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "The file name to store it under. Defaults to the one in the path."
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "The alt text for an image, or a note on a file."
                                    },
                                    "access": {
                                        "type": "object",
                                        "description": "Who may see or download it, in the usual mode and groups shape."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "path": {
                                                    "type": "string",
                                                    "description": "Relative to the upload folder."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "Absolute, ready to display."
                                                },
                                                "ordering": {
                                                    "type": "integer",
                                                    "description": "Where it sits among the others; the first image is the one the shop shows."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The alt text for an image, or a note on a file."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Who may see or download it."
                                                },
                                                "free_download": {
                                                    "type": "boolean",
                                                    "description": "Files only: whether it can be downloaded without buying the product."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "bad_type: The extension is not one this shop accepts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "write_failed: The upload folder refused the file, which is usually a permissions problem.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/files/{fileId}": {
            "put": {
                "operationId": "put-products-id-files-fileid",
                "summary": "Edit an image or a file",
                "description": "Changes the name, the description or the access of something already attached, without re-uploading\nthe bytes.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "fileId",
                        "in": "path",
                        "required": true,
                        "description": "The image or file.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Any of `name`, `description`, `access` and, for a file, `free_download`. What you do not send is left alone.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "path": {
                                                    "type": "string",
                                                    "description": "Relative to the upload folder."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "Absolute, ready to display."
                                                },
                                                "ordering": {
                                                    "type": "integer",
                                                    "description": "Where it sits among the others; the first image is the one the shop shows."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The alt text for an image, or a note on a file."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Who may see or download it."
                                                },
                                                "free_download": {
                                                    "type": "boolean",
                                                    "description": "Files only: whether it can be downloaded without buying the product."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such file on that product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-products-id-files-fileid",
                "summary": "Remove an image or a file",
                "description": "Detaches an image or a file from a product.\n\nThe bytes stay in the upload folder: another product may be using the same file, and the API will\nnot delete somebody's media because one product stopped pointing at it.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "fileId",
                        "in": "path",
                        "required": true,
                        "description": "The image or file.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "What was detached."
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "True when the row is gone."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such file on that product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/media/order": {
            "put": {
                "operationId": "put-products-id-media-order",
                "summary": "Reorder images and files",
                "description": "Sets the order of a product's images or files. The first image is the one the shop shows, so this is\nhow you choose it.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "images": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        },
                                        "description": "File ids in the order you want them."
                                    },
                                    "files": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        },
                                        "description": "The same for downloadable files."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "images": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute, ready to display."
                                                            },
                                                            "ordering": {
                                                                "type": "integer",
                                                                "description": "Where it sits among the others; the first image is the one the shop shows."
                                                            },
                                                            "description": {
                                                                "type": "string",
                                                                "description": "The alt text for an image, or a note on a file."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                                    }
                                                                },
                                                                "description": "Who may see or download it."
                                                            },
                                                            "free_download": {
                                                                "type": "boolean",
                                                                "description": "Files only: whether it can be downloaded without buying the product."
                                                            }
                                                        }
                                                    },
                                                    "description": "The images as they now stand, in their new order, each in the same shape as on the product."
                                                },
                                                "files": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "path": {
                                                                "type": "string",
                                                                "description": "Relative to the upload folder."
                                                            },
                                                            "url": {
                                                                "type": "string",
                                                                "description": "Absolute, ready to display."
                                                            },
                                                            "ordering": {
                                                                "type": "integer",
                                                                "description": "Where it sits among the others; the first image is the one the shop shows."
                                                            },
                                                            "description": {
                                                                "type": "string",
                                                                "description": "The alt text for an image, or a note on a file."
                                                            },
                                                            "access": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "mode": {
                                                                        "type": "string",
                                                                        "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                                    },
                                                                    "groups": {
                                                                        "type": "array",
                                                                        "items": {
                                                                            "type": "integer"
                                                                        },
                                                                        "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                                    }
                                                                },
                                                                "description": "Who may see or download it."
                                                            },
                                                            "free_download": {
                                                                "type": "boolean",
                                                                "description": "Files only: whether it can be downloaded without buying the product."
                                                            }
                                                        }
                                                    },
                                                    "description": "The files as they now stand, in the same shape as on the product."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/media/content": {
            "get": {
                "operationId": "get-media-content",
                "summary": "The bytes of an image",
                "description": "The bytes of one image from the upload folder, so a client can edit it: crop it, rotate it, and send\nit back.\n\nThis is the one route that does not answer with the envelope. It answers with the file, and with the\ncross-origin header that lets a browser read it into a canvas, which the shop's own image URLs do\nnot carry. Without it, a web client cannot export an edited image at all.\n\nA path that tries to leave the upload folder is refused rather than resolved.",
                "tags": [
                    "media"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "path",
                        "in": "query",
                        "required": true,
                        "description": "The image, relative to the upload folder.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": []
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such file, or a path that tried to leave the upload folder.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/fields/{table}/{namekey}/file": {
            "post": {
                "operationId": "post-fields-table-namekey-file",
                "summary": "Upload the value of a file field",
                "description": "Uploads the file that is the value of one of your own custom fields. Only the two field types that\nhold one accept it: `ajaximage` and `ajaxfile`.\n\nThe field is named rather than numbered, and the table says which kind of record it belongs to, so\nthe same route serves a product field, a category field and a customer field.",
                "tags": [
                    "fields"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "table",
                        "in": "path",
                        "required": true,
                        "description": "Which kind of record: `product`, `category`, `user`, `order`, `address`.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "namekey",
                        "in": "path",
                        "required": true,
                        "description": "The field, as `fields[].namekey` gives it.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "The bytes, base64 encoded."
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "The file name to store it under."
                                    }
                                },
                                "required": [
                                    "data"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "path": {
                                                    "type": "string",
                                                    "description": "Relative to the field's own upload folder. This is the value to store on the record."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "The file name it was stored under."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "Absolute, where the shop serves it from."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such record kind.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "bad_field: No such field, or it does not hold a file. bad_type: The extension is not one this shop accepts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "write_failed: The upload folder refused the file.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/methods": {
            "get": {
                "operationId": "get-orders-id-methods",
                "summary": "The shipping and payment methods an order can move to",
                "description": "What this order could ship and be paid by, with what it uses now, so a change can be offered as a\nchoice rather than as free text.\n\nA method is identified by its plugin and its instance together, written `plugin_id`, which is the\npairing the backend posts back. An order that ships from several warehouses carries one method per\nshipment, and `multiple` says so.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "shipping": {
                                                    "type": "object",
                                                    "properties": {
                                                        "current": {
                                                            "type": "string",
                                                            "description": "What the order uses now, as `plugin_id`. `_` when nothing is set, so the current one always matches an option."
                                                        },
                                                        "multiple": {
                                                            "type": "boolean",
                                                            "description": "True when the order ships in several shipments and carries a method for each."
                                                        },
                                                        "options": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "value": {
                                                                        "type": "string",
                                                                        "description": "The `plugin_id` pairing to send when changing the method."
                                                                    },
                                                                    "label": {
                                                                        "type": "string",
                                                                        "description": "As the merchant named it."
                                                                    }
                                                                }
                                                            },
                                                            "description": "What it could move to."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "object"
                                                            },
                                                            "description": "For an order that ships in several shipments, the shipments and the method chosen for each. Empty otherwise."
                                                        }
                                                    },
                                                    "description": "The shipping choice."
                                                },
                                                "payment": {
                                                    "type": "object",
                                                    "properties": {
                                                        "current": {
                                                            "type": "string",
                                                            "description": "What the order uses now."
                                                        },
                                                        "multiple": {
                                                            "type": "boolean",
                                                            "description": "Always false: an order is paid one way."
                                                        },
                                                        "options": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "value": {
                                                                        "type": "string",
                                                                        "description": "The `plugin_id` pairing to send."
                                                                    },
                                                                    "label": {
                                                                        "type": "string",
                                                                        "description": "As the merchant named it."
                                                                    }
                                                                }
                                                            },
                                                            "description": "What it could move to."
                                                        }
                                                    },
                                                    "description": "The payment choice, in the same shape."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not see it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/customers/{id}/addresses/{aid}/default": {
            "put": {
                "operationId": "put-customers-id-addresses-aid-default",
                "summary": "Make an address the default",
                "description": "Marks one of a customer's addresses as their default, and answers with the customer as it now\nstands.\n\nThe default is per kind: an address used for billing becomes the default billing address, and the\none it replaces stops being it. Nothing is sent in the body.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "aid",
                        "in": "path",
                        "required": true,
                        "description": "The address, from `addresses[].id`.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/characteristics": {
            "post": {
                "operationId": "post-products-characteristics",
                "summary": "Create a characteristic or one of its values",
                "description": "Creates a characteristic, such as Size, or a value of one, such as XL.\n\nSend a `name` for a characteristic, or a `value` with the `parent_id` of the characteristic it\nbelongs to. They are the same records at two levels, which is why one route serves both.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "The name of a new characteristic. Give this or `value`."
                                    },
                                    "value": {
                                        "type": "string",
                                        "description": "The name of a new value, with `parent_id`."
                                    },
                                    "parent_id": {
                                        "type": "integer",
                                        "description": "The characteristic a value belongs to."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "What was created, which is what a variant refers to."
                                                },
                                                "value": {
                                                    "type": "string",
                                                    "description": "Its name."
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "`0` for a characteristic, the characteristic for a value."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request: Neither a name nor a value was given.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The shop refused to save it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/categories": {
            "post": {
                "operationId": "post-products-categories",
                "summary": "Create a product category",
                "description": "Creates a category under another, or at the top of the product tree when no parent is given.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "Its name."
                                    },
                                    "parent_id": {
                                        "type": "integer",
                                        "description": "The category to put it under. Omit for the top of the tree."
                                    },
                                    "published": {
                                        "type": "boolean",
                                        "description": "Defaults to published."
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "The long description, as HTML."
                                    },
                                    "meta_description": {
                                        "type": "string",
                                        "description": "SEO description."
                                    },
                                    "access": {
                                        "type": "object",
                                        "description": "Who may see it."
                                    },
                                    "custom_fields": {
                                        "type": "object",
                                        "description": "Your own category fields, keyed by namekey."
                                    }
                                },
                                "required": [
                                    "name"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The category that was created."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "Where it sits."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: One of your own fields was rejected by its own rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The shop refused to save it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/manufacturers": {
            "post": {
                "operationId": "post-products-manufacturers",
                "summary": "Create a manufacturer",
                "description": "Creates a brand. HikaShop keeps manufacturers in the category tree under their own root, so this\ntakes the same fields as a category and answers the same way.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "The brand name."
                                    },
                                    "parent_id": {
                                        "type": "integer",
                                        "description": "A manufacturer to nest it under, which most shops do not use."
                                    },
                                    "published": {
                                        "type": "boolean",
                                        "description": "Defaults to published."
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "The long description, as HTML."
                                    },
                                    "meta_description": {
                                        "type": "string",
                                        "description": "SEO description."
                                    },
                                    "access": {
                                        "type": "object",
                                        "description": "Who may see it."
                                    },
                                    "custom_fields": {
                                        "type": "object",
                                        "description": "Your own category fields."
                                    }
                                },
                                "required": [
                                    "name"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The manufacturer that was created, which is what `manufacturer_id` on a product stores."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "parent_id": {
                                                    "type": "integer",
                                                    "description": "Its root."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: One of your own fields was rejected by its own rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The shop refused to save it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/discounts/{id}": {
            "get": {
                "operationId": "get-discounts-id",
                "summary": "Read one discount or coupon",
                "description": "One reduction with every restriction it carries.",
                "tags": [
                    "discounts"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The discount or coupon.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`discount` applies by itself, `coupon` waits for its code."
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "What the customer types. Empty on a discount."
                                                },
                                                "kind": {
                                                    "type": "string",
                                                    "description": "Whether the value is a percentage or a fixed amount."
                                                },
                                                "value": {
                                                    "type": "number",
                                                    "description": "The reduction, read according to `kind`."
                                                },
                                                "currency_id": {
                                                    "type": "integer",
                                                    "description": "The currency a fixed amount is in."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "start": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp before which it does not apply."
                                                },
                                                "end": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp after which it expires."
                                                },
                                                "minimum_order": {
                                                    "type": "number",
                                                    "description": "Order total below which it does not apply, `0` for none."
                                                },
                                                "maximum_order": {
                                                    "type": "number",
                                                    "description": "Order total above which it stops applying, `0` for none."
                                                },
                                                "quota": {
                                                    "type": "integer",
                                                    "description": "How many times it may be used in total, `0` for no limit."
                                                },
                                                "quota_per_user": {
                                                    "type": "integer",
                                                    "description": "How many times one customer may use it, `0` for no limit."
                                                },
                                                "used_times": {
                                                    "type": "integer",
                                                    "description": "How many times it already has been."
                                                },
                                                "tax_included": {
                                                    "type": "boolean",
                                                    "description": "Whether the value is understood as tax included."
                                                },
                                                "tax_id": {
                                                    "type": "integer",
                                                    "description": "The tax category of the reduction itself."
                                                },
                                                "shipping_percent": {
                                                    "type": "number",
                                                    "description": "A reduction on the shipping rather than on the goods."
                                                },
                                                "minimum_products": {
                                                    "type": "integer",
                                                    "description": "Fewest items in the cart for it to apply."
                                                },
                                                "maximum_products": {
                                                    "type": "integer",
                                                    "description": "Most items for it to still apply."
                                                },
                                                "product_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these products. Empty means all of them."
                                                },
                                                "exclude_product_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Never applies to these."
                                                },
                                                "category_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these categories."
                                                },
                                                "category_childs": {
                                                    "type": "boolean",
                                                    "description": "Whether those categories include their sub-categories."
                                                },
                                                "exclude_category_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Never applies in these categories."
                                                },
                                                "exclude_category_childs": {
                                                    "type": "boolean",
                                                    "description": "Whether those exclusions include sub-categories."
                                                },
                                                "zone_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these zones."
                                                },
                                                "user_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these customers."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Which user groups it is for, in the usual `mode` and `groups` shape."
                                                },
                                                "exclude_access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Which user groups it is never for."
                                                },
                                                "auto_load": {
                                                    "type": "boolean",
                                                    "description": "For a coupon, whether the shop applies it without the customer typing it."
                                                },
                                                "product_only": {
                                                    "type": "boolean",
                                                    "description": "Whether it reduces only the goods and leaves the fees alone."
                                                },
                                                "discounted_products": {
                                                    "type": "integer",
                                                    "description": "How many products in the cart it applied to, on a discount that has been used."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such discount, or the operator may not see it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-discounts-id",
                "summary": "Update a discount or a coupon",
                "description": "Changes the fields you send and leaves the rest alone, and answers with the reduction as it now\nstands.",
                "tags": [
                    "discounts"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The discount or coupon.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Any field of a discount. What you do not send keeps its value. A restriction list you do send replaces the one it had.",
                                "additionalProperties": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`discount` applies by itself, `coupon` waits for its code."
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "What the customer types. Empty on a discount."
                                                },
                                                "kind": {
                                                    "type": "string",
                                                    "description": "Whether the value is a percentage or a fixed amount."
                                                },
                                                "value": {
                                                    "type": "number",
                                                    "description": "The reduction, read according to `kind`."
                                                },
                                                "currency_id": {
                                                    "type": "integer",
                                                    "description": "The currency a fixed amount is in."
                                                },
                                                "published": {
                                                    "type": "boolean"
                                                },
                                                "start": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp before which it does not apply."
                                                },
                                                "end": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp after which it expires."
                                                },
                                                "minimum_order": {
                                                    "type": "number",
                                                    "description": "Order total below which it does not apply, `0` for none."
                                                },
                                                "maximum_order": {
                                                    "type": "number",
                                                    "description": "Order total above which it stops applying, `0` for none."
                                                },
                                                "quota": {
                                                    "type": "integer",
                                                    "description": "How many times it may be used in total, `0` for no limit."
                                                },
                                                "quota_per_user": {
                                                    "type": "integer",
                                                    "description": "How many times one customer may use it, `0` for no limit."
                                                },
                                                "used_times": {
                                                    "type": "integer",
                                                    "description": "How many times it already has been."
                                                },
                                                "tax_included": {
                                                    "type": "boolean",
                                                    "description": "Whether the value is understood as tax included."
                                                },
                                                "tax_id": {
                                                    "type": "integer",
                                                    "description": "The tax category of the reduction itself."
                                                },
                                                "shipping_percent": {
                                                    "type": "number",
                                                    "description": "A reduction on the shipping rather than on the goods."
                                                },
                                                "minimum_products": {
                                                    "type": "integer",
                                                    "description": "Fewest items in the cart for it to apply."
                                                },
                                                "maximum_products": {
                                                    "type": "integer",
                                                    "description": "Most items for it to still apply."
                                                },
                                                "product_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these products. Empty means all of them."
                                                },
                                                "exclude_product_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Never applies to these."
                                                },
                                                "category_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these categories."
                                                },
                                                "category_childs": {
                                                    "type": "boolean",
                                                    "description": "Whether those categories include their sub-categories."
                                                },
                                                "exclude_category_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Never applies in these categories."
                                                },
                                                "exclude_category_childs": {
                                                    "type": "boolean",
                                                    "description": "Whether those exclusions include sub-categories."
                                                },
                                                "zone_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these zones."
                                                },
                                                "user_ids": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "integer"
                                                    },
                                                    "description": "Restricted to these customers."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Which user groups it is for, in the usual `mode` and `groups` shape."
                                                },
                                                "exclude_access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Which user groups it is never for."
                                                },
                                                "auto_load": {
                                                    "type": "boolean",
                                                    "description": "For a coupon, whether the shop applies it without the customer typing it."
                                                },
                                                "product_only": {
                                                    "type": "boolean",
                                                    "description": "Whether it reduces only the goods and leaves the fees alone."
                                                },
                                                "discounted_products": {
                                                    "type": "integer",
                                                    "description": "How many products in the cart it applied to, on a discount that has been used."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such discount, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "code_required: A coupon needs a code, so it cannot be cleared on one. code_taken: Another coupon already uses that code. value_required: A reduction needs a value.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The shop refused to save it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-discounts-id",
                "summary": "Delete a discount or a coupon",
                "description": "Deletes a reduction. Orders that already used it keep the amount they were given: the discount on\nan order is a figure, not a pointer at this row.",
                "tags": [
                    "discounts"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The discount or coupon.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "True when the row is gone."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such discount, or the operator may not delete it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/products/{id}/files": {
            "post": {
                "operationId": "post-products-id-files",
                "summary": "Attach a downloadable file",
                "description": "The same as attaching an image, for the files a customer downloads after buying. `free_download`\ndecides whether they have to buy it first.",
                "tags": [
                    "products"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The product.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "data": {
                                        "type": "string",
                                        "description": "The bytes, base64 encoded. Give this or `path`."
                                    },
                                    "path": {
                                        "type": "string",
                                        "description": "A file already in the upload folder."
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "The file name to store it under."
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "A note on the file."
                                    },
                                    "access": {
                                        "type": "object",
                                        "description": "Who may download it."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "path": {
                                                    "type": "string",
                                                    "description": "Relative to the upload folder."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "Absolute, ready to display."
                                                },
                                                "ordering": {
                                                    "type": "integer",
                                                    "description": "Where it sits among the others; the first image is the one the shop shows."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "The alt text for an image, or a note on a file."
                                                },
                                                "access": {
                                                    "type": "object",
                                                    "properties": {
                                                        "mode": {
                                                            "type": "string",
                                                            "description": "`all`, `none`, or `groups` when it is restricted to some."
                                                        },
                                                        "groups": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "integer"
                                                            },
                                                            "description": "User **group** ids, and not Joomla view levels. The two id spaces overlap and disagree, so a value that looks plausible can grant the wrong audience."
                                                        }
                                                    },
                                                    "description": "Who may see or download it."
                                                },
                                                "free_download": {
                                                    "type": "boolean",
                                                    "description": "Files only: whether it can be downloaded without buying the product."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such product, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "bad_type: The extension is not one this shop accepts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "write_failed: The upload folder refused the file.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/customers/{id}/addresses": {
            "get": {
                "operationId": "get-customers-id-addresses",
                "summary": "A blank address form",
                "description": "The address form of a customer: the shop's own address fields, and the values of the address asked\nfor. Without an address id it is a blank form, which is what you draw to add one.\n\nThe form comes with the values because a shop decides its own address fields, so build from\n`fields` rather than assuming a shape.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "address_id": {
                                                    "type": "integer",
                                                    "description": "The address this form is for, `0` for a new one."
                                                },
                                                "types": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Which of `billing` and `shipping` it is used for."
                                                },
                                                "default": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Which kind it is the default for, `null` when it is not a default."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key its value is stored under."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "What to render: `text`, `radio`, `singledropdown`, `file`, and the rest."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "What to send back when this choice is picked."
                                                                        },
                                                                        "label": {
                                                                            "type": "string",
                                                                            "description": "What to show."
                                                                        },
                                                                        "label_key": {
                                                                            "type": "string",
                                                                            "description": "The translation key behind the label, when there is one."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The choices, for a field that has them."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one may be chosen."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The shop's address fields, in display order."
                                                },
                                                "values": {
                                                    "type": "object",
                                                    "description": "The current values, keyed by field namekey. Empty on a blank form. Keyed by whatever address fields this shop has.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "country_name": {
                                                    "type": "string",
                                                    "description": "The country spelled out, since the value is a zone namekey."
                                                },
                                                "state_name": {
                                                    "type": "string",
                                                    "description": "The state spelled out, empty where the country has none."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not see them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "post-customers-id-addresses",
                "summary": "Add an address",
                "description": "Writes an address of a customer. Without an address id it creates one; with one it saves that one.\n\n`types` says what the address is for, billing or shipping or both, and `default` makes it the\ndefault for those. An address is validated by the shop's own field rules, so a missing required\nfield is refused rather than half-saved.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fields": {
                                        "type": "object",
                                        "description": "Keyed by address field namekey, the same keys the form returned in `values`."
                                    },
                                    "types": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Which of `billing` and `shipping` this address is for. Defaults to both."
                                    },
                                    "default": {
                                        "type": "boolean",
                                        "description": "Make it the default for its types."
                                    }
                                },
                                "required": [
                                    "fields"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: A field was rejected by its own rules. invalid_address: The address is not one the shop will accept, usually a missing required field.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-customers-id-addresses",
                "summary": "Add an address",
                "description": "Writes an address of a customer. Without an address id it creates one; with one it saves that one.\n\n`types` says what the address is for, billing or shipping or both, and `default` makes it the\ndefault for those. An address is validated by the shop's own field rules, so a missing required\nfield is refused rather than half-saved.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fields": {
                                        "type": "object",
                                        "description": "Keyed by address field namekey, the same keys the form returned in `values`."
                                    },
                                    "types": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Which of `billing` and `shipping` this address is for. Defaults to both."
                                    },
                                    "default": {
                                        "type": "boolean",
                                        "description": "Make it the default for its types."
                                    }
                                },
                                "required": [
                                    "fields"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: A field was rejected by its own rules. invalid_address: The address is not one the shop will accept, usually a missing required field.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-customers-id-addresses",
                "summary": "Delete an address",
                "description": "Removes an address from a customer. Orders that used it keep their own copy of it.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/customers/{customerId}/addresses/{addressId}": {
            "get": {
                "operationId": "get-customers-customerid-addresses-addressid",
                "summary": "An address with its form",
                "description": "The address form of a customer: the shop's own address fields, and the values of the address asked\nfor. Without an address id it is a blank form, which is what you draw to add one.\n\nThe form comes with the values because a shop decides its own address fields, so build from\n`fields` rather than assuming a shape.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "addressId",
                        "in": "path",
                        "required": true,
                        "description": "The address.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "address_id": {
                                                    "type": "integer",
                                                    "description": "The address this form is for, `0` for a new one."
                                                },
                                                "types": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Which of `billing` and `shipping` it is used for."
                                                },
                                                "default": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Which kind it is the default for, `null` when it is not a default."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The key its value is stored under."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "What to render: `text`, `radio`, `singledropdown`, `file`, and the rest."
                                                            },
                                                            "raw_type": {
                                                                "type": "string",
                                                                "description": "HikaShop's own name for the type."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Translated into the operator's language."
                                                            },
                                                            "default": {
                                                                "type": "string",
                                                                "description": "The value used when none is given."
                                                            },
                                                            "required": {
                                                                "type": "boolean",
                                                                "description": "Whether the shop refuses to save without it."
                                                            },
                                                            "options": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "value": {
                                                                            "type": "string",
                                                                            "description": "What to send back when this choice is picked."
                                                                        },
                                                                        "label": {
                                                                            "type": "string",
                                                                            "description": "What to show."
                                                                        },
                                                                        "label_key": {
                                                                            "type": "string",
                                                                            "description": "The translation key behind the label, when there is one."
                                                                        }
                                                                    }
                                                                },
                                                                "description": "The choices, for a field that has them."
                                                            },
                                                            "multiple": {
                                                                "type": "boolean",
                                                                "description": "Whether more than one may be chosen."
                                                            },
                                                            "translatable": {
                                                                "type": "boolean",
                                                                "description": "Whether its value can be translated."
                                                            },
                                                            "upload_dir": {
                                                                "type": "string",
                                                                "description": "For a file field, where its uploads are kept."
                                                            },
                                                            "allowed_extensions": {
                                                                "type": "string",
                                                                "description": "For a file field, the extensions it accepts. Empty means the shop default."
                                                            },
                                                            "date_format": {
                                                                "type": "string",
                                                                "description": "For a date field, the format it is stored in."
                                                            }
                                                        }
                                                    },
                                                    "description": "The shop's address fields, in display order."
                                                },
                                                "values": {
                                                    "type": "object",
                                                    "description": "The current values, keyed by field namekey. Empty on a blank form. Keyed by whatever address fields this shop has.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "country_name": {
                                                    "type": "string",
                                                    "description": "The country spelled out, since the value is a zone namekey."
                                                },
                                                "state_name": {
                                                    "type": "string",
                                                    "description": "The state spelled out, empty where the country has none."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not see them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "post-customers-customerid-addresses-addressid",
                "summary": "Save an address",
                "description": "Writes an address of a customer. Without an address id it creates one; with one it saves that one.\n\n`types` says what the address is for, billing or shipping or both, and `default` makes it the\ndefault for those. An address is validated by the shop's own field rules, so a missing required\nfield is refused rather than half-saved.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "addressId",
                        "in": "path",
                        "required": true,
                        "description": "The address.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fields": {
                                        "type": "object",
                                        "description": "Keyed by address field namekey, the same keys the form returned in `values`."
                                    },
                                    "types": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Which of `billing` and `shipping` this address is for. Defaults to both."
                                    },
                                    "default": {
                                        "type": "boolean",
                                        "description": "Make it the default for its types."
                                    }
                                },
                                "required": [
                                    "fields"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: A field was rejected by its own rules. invalid_address: The address is not one the shop will accept, usually a missing required field.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "operationId": "put-customers-customerid-addresses-addressid",
                "summary": "Save an address",
                "description": "Writes an address of a customer. Without an address id it creates one; with one it saves that one.\n\n`types` says what the address is for, billing or shipping or both, and `default` makes it the\ndefault for those. An address is validated by the shop's own field rules, so a missing required\nfield is refused rather than half-saved.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "addressId",
                        "in": "path",
                        "required": true,
                        "description": "The address.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fields": {
                                        "type": "object",
                                        "description": "Keyed by address field namekey, the same keys the form returned in `values`."
                                    },
                                    "types": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Which of `billing` and `shipping` this address is for. Defaults to both."
                                    },
                                    "default": {
                                        "type": "boolean",
                                        "description": "Make it the default for its types."
                                    }
                                },
                                "required": [
                                    "fields"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_fields: A field was rejected by its own rules. invalid_address: The address is not one the shop will accept, usually a missing required field.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "delete-customers-customerid-addresses-addressid",
                "summary": "Delete an address",
                "description": "Removes an address from a customer. Orders that used it keep their own copy of it.",
                "tags": [
                    "customers"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "description": "The customer.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "addressId",
                        "in": "path",
                        "required": true,
                        "description": "The address.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The HikaShop customer id, which is what every customer route takes."
                                                },
                                                "cms_id": {
                                                    "type": "integer",
                                                    "description": "The Joomla or WordPress user id, `0` for a guest with no account."
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "email": {
                                                    "type": "string"
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "The login, empty for a guest."
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "description": "`registered` or `guest`."
                                                },
                                                "blocked": {
                                                    "type": "boolean",
                                                    "description": "Whether the CMS account is disabled."
                                                },
                                                "can_edit_account": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change the login and password of this particular account. False for an account above their own level, which is how a super user is protected from staff."
                                                },
                                                "groups_editable": {
                                                    "type": "boolean",
                                                    "description": "Whether this operator may change which groups the customer is in."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "description": "The groups they are in."
                                                },
                                                "available_groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "assignable": {
                                                                "type": "boolean",
                                                                "description": "False for a group this operator may not grant."
                                                            }
                                                        }
                                                    },
                                                    "description": "Every group, with whether this operator may put the customer into it, so a picker can grey out the rest rather than offering a refusal."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the first time the shop saw them."
                                                },
                                                "addresses": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "types": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                },
                                                                "description": "Which of `billing` and `shipping` it is used for."
                                                            },
                                                            "name": {
                                                                "type": "string"
                                                            },
                                                            "company": {
                                                                "type": "string"
                                                            },
                                                            "street": {
                                                                "type": "string"
                                                            },
                                                            "city": {
                                                                "type": "string"
                                                            },
                                                            "post_code": {
                                                                "type": "string"
                                                            },
                                                            "telephone": {
                                                                "type": "string"
                                                            },
                                                            "default": {
                                                                "type": "boolean",
                                                                "description": "Whether it is the default for one of its types."
                                                            },
                                                            "formatted": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "text": {
                                                                        "type": "string",
                                                                        "description": "Several lines, for an invoice or a label."
                                                                    },
                                                                    "one_line": {
                                                                        "type": "string",
                                                                        "description": "One line, for a list."
                                                                    }
                                                                },
                                                                "description": "The address laid out the way this shop lays addresses out, which depends on its address format setting."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their addresses, defaults first."
                                                },
                                                "orders": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "number": {
                                                                "type": "string",
                                                                "description": "The number the customer sees."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "A namekey."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "total": {
                                                                "type": "number",
                                                                "description": "Tax included, in the order currency."
                                                            },
                                                            "currency_id": {
                                                                "type": "integer",
                                                                "description": "That currency."
                                                            }
                                                        }
                                                    },
                                                    "description": "Their orders, newest first, enough to list them."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own customer fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such customer or address, or the operator may not change them.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/pair": {
            "post": {
                "operationId": "post-pair",
                "summary": "Redeem a pairing code",
                "description": "Exchanges a single-use code, generated in **System > App Devices** of the shop's backend, for the\ndevice's own token. This is the only route that answers without one.\n\nThe token comes back **once**. Only its hash is stored, so a lost token is re-paired, never\nrecovered. Attempts are rate limited per address.",
                "tags": [
                    "pair"
                ],
                "x-since": "6.6.0",
                "x-scopes": [],
                "security": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "code": {
                                        "type": "string",
                                        "description": "The pairing code as shown in the backend. Case and spacing are normalised, so the grouping dash is optional."
                                    },
                                    "device_name": {
                                        "type": "string",
                                        "description": "What to call this device in the device list. Defaults to `Device`."
                                    },
                                    "platform": {
                                        "type": "string",
                                        "description": "A free label kept for the listing. Anything that is not a letter, a digit, a dash or an underscore is stripped."
                                    }
                                },
                                "required": [
                                    "code"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "token": {
                                                    "type": "string",
                                                    "description": "Send this as the bearer token from now on. It is not retrievable again."
                                                },
                                                "scopes": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "`read`, and `write` when the code granted it."
                                                },
                                                "device_id": {
                                                    "type": "integer",
                                                    "description": "The row in the device list, which is what you revoke later."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_request: No code was sent.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "invalid_code: The code is unknown, already used, or expired.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "too_many_requests: Too many attempts from this address.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}": {
            "get": {
                "operationId": "get-orders-id",
                "summary": "Read one order",
                "description": "The whole order: its lines, its totals, its addresses, its history and your own fields.\n\nMoney is in the currency the order was placed in, which is not necessarily the shop's. Do not\nconvert it: an order is a record of what was agreed at the time.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "number": {
                                                    "type": "string",
                                                    "description": "The number the customer sees."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "A namekey."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp."
                                                },
                                                "modified": {
                                                    "type": "integer",
                                                    "description": "Unix timestamp of the last change."
                                                },
                                                "currency_id": {
                                                    "type": "integer",
                                                    "description": "The currency the order was placed in."
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "properties": {
                                                        "total": {
                                                            "type": "number",
                                                            "description": "What the customer owes, tax included."
                                                        },
                                                        "discount": {
                                                            "type": "number",
                                                            "description": "The discount applied, as a positive figure already subtracted."
                                                        },
                                                        "shipping": {
                                                            "type": "number",
                                                            "description": "The shipping charged."
                                                        },
                                                        "payment": {
                                                            "type": "number",
                                                            "description": "The payment fee charged."
                                                        },
                                                        "tax": {
                                                            "type": "number",
                                                            "description": "The tax within the total, not on top of it."
                                                        }
                                                    },
                                                    "description": "The figures. See the shape below."
                                                },
                                                "customer": {
                                                    "type": "object",
                                                    "properties": {
                                                        "name": {
                                                            "type": "string"
                                                        },
                                                        "email": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "description": "Who placed it."
                                                },
                                                "payment_method": {
                                                    "type": "string",
                                                    "description": "How it was paid, as the shop names it."
                                                },
                                                "shipping_method": {
                                                    "type": "string",
                                                    "description": "How it ships."
                                                },
                                                "invoice_number": {
                                                    "type": "string",
                                                    "description": "Empty until an invoice has been issued."
                                                },
                                                "invoice_created": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Unix timestamp of the invoice."
                                                },
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The line id, which is what `PUT /orders/{id}/products/{lineId}` takes. It is not the product id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "The product as it was named when ordered, which may since have changed."
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "description": "Its SKU at the time."
                                                            },
                                                            "quantity": {
                                                                "type": "integer"
                                                            },
                                                            "price": {
                                                                "type": "number",
                                                                "description": "Unit price, tax excluded, as agreed at the time."
                                                            },
                                                            "tax": {
                                                                "type": "number",
                                                                "description": "Tax on the line."
                                                            },
                                                            "editable": {
                                                                "type": "boolean",
                                                                "description": "False once the line can no longer be changed, for instance on a shipped order."
                                                            }
                                                        }
                                                    },
                                                    "description": "The lines: `id`, `name`, `code`, `quantity`, `price`, `tax` and whether the line can still be edited."
                                                },
                                                "billing_address": {
                                                    "type": [
                                                        "object",
                                                        "null"
                                                    ],
                                                    "description": "The address as it was at the time, `null` when there is none. It is a copy, not a pointer at the customer's current address."
                                                },
                                                "shipping_address": {
                                                    "type": [
                                                        "object",
                                                        "null"
                                                    ],
                                                    "description": "The same, for delivery."
                                                },
                                                "shipping_address_override": {
                                                    "type": "boolean",
                                                    "description": "Whether the delivery address was set apart from the billing one."
                                                },
                                                "history": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "status": {
                                                                "type": "string",
                                                                "description": "The namekey it moved to."
                                                            },
                                                            "created": {
                                                                "type": "integer",
                                                                "description": "Unix timestamp."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "What caused it: a payment notification, an operator, the shop itself."
                                                            },
                                                            "reason": {
                                                                "type": "string",
                                                                "description": "The note recorded with the change, when there was one."
                                                            },
                                                            "notified": {
                                                                "type": "boolean",
                                                                "description": "Whether the customer was emailed about it."
                                                            }
                                                        }
                                                    },
                                                    "description": "What has happened to the order, oldest first."
                                                },
                                                "fields": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The definitions of your own order fields."
                                                },
                                                "custom_fields": {
                                                    "type": "object",
                                                    "description": "Their values, keyed by namekey. The keys depend on the shop; `fields` says what they are.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "custom_field_files": {
                                                    "type": "object",
                                                    "description": "For a field holding a file, the file behind the value. Keyed the same way.",
                                                    "additionalProperties": true,
                                                    "x-open": true
                                                },
                                                "fees": {
                                                    "type": "object",
                                                    "properties": {
                                                        "discount": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "A positive figure, already subtracted from the total."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "code": {
                                                                    "type": "string",
                                                                    "description": "The coupon code, empty for a discount applied by hand."
                                                                }
                                                            },
                                                            "description": "Its `amount`, its `tax`, the `tax_namekeys` behind that tax, and the coupon `code` when one was used."
                                                        },
                                                        "shipping": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that handled it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The shipping charge and what carried it."
                                                        },
                                                        "payment": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that took it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The payment fee and what took it."
                                                        }
                                                    },
                                                    "description": "The `discount`, `shipping` and `payment` amounts, which is what `PUT /orders/{id}/fees` writes."
                                                },
                                                "tax_rates": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "namekey": {
                                                                "type": "string",
                                                                "description": "The tax rate as the shop names it."
                                                            },
                                                            "rate": {
                                                                "type": "number",
                                                                "description": "As a fraction, so `0.1` is ten percent."
                                                            }
                                                        }
                                                    },
                                                    "description": "The rates that made up the tax, each with its namekey and rate, so a total can be explained rather than only shown."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/fees": {
            "put": {
                "operationId": "put-orders-id-fees",
                "summary": "Set the order fees",
                "description": "Replaces the discount, shipping and payment amounts and re-totals the order, so a client does not\nhave to compute a total itself and risk disagreeing with the shop.\n\nWhat you do not send keeps its current value.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fees": {
                                        "type": "object",
                                        "description": "Any of `discount`, `shipping` and `payment`, each an object with at least an `amount`, tax excluded. A discount is a positive figure and is subtracted."
                                    }
                                },
                                "required": [
                                    "fees"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "fees": {
                                                    "type": "object",
                                                    "properties": {
                                                        "discount": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "A positive figure, already subtracted from the total."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "code": {
                                                                    "type": "string",
                                                                    "description": "The coupon code, empty for a discount applied by hand."
                                                                }
                                                            },
                                                            "description": "Its `amount`, its `tax`, the `tax_namekeys` behind that tax, and the coupon `code` when one was used."
                                                        },
                                                        "shipping": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that handled it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The shipping charge and what carried it."
                                                        },
                                                        "payment": {
                                                            "type": "object",
                                                            "properties": {
                                                                "amount": {
                                                                    "type": "number",
                                                                    "description": "Tax excluded."
                                                                },
                                                                "tax": {
                                                                    "type": "number",
                                                                    "description": "The tax on it."
                                                                },
                                                                "tax_namekeys": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "string"
                                                                    },
                                                                    "description": "Which tax rates that came from."
                                                                },
                                                                "method": {
                                                                    "type": "string",
                                                                    "description": "The plugin that took it."
                                                                },
                                                                "method_name": {
                                                                    "type": "string",
                                                                    "description": "As the merchant named it."
                                                                }
                                                            },
                                                            "description": "The payment fee and what took it."
                                                        }
                                                    },
                                                    "description": "The discount, shipping and payment amounts of the order."
                                                },
                                                "totals": {
                                                    "type": "object",
                                                    "properties": {
                                                        "total": {
                                                            "type": "number",
                                                            "description": "What the customer owes, tax included."
                                                        },
                                                        "discount": {
                                                            "type": "number",
                                                            "description": "The discount applied, as a positive figure already subtracted."
                                                        },
                                                        "shipping": {
                                                            "type": "number",
                                                            "description": "The shipping charged."
                                                        },
                                                        "payment": {
                                                            "type": "number",
                                                            "description": "The payment fee charged."
                                                        },
                                                        "tax": {
                                                            "type": "number",
                                                            "description": "The tax within the total, not on top of it."
                                                        }
                                                    },
                                                    "description": "The order totalled, so a client need not compute it and disagree with the shop."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not change it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/coupons": {
            "get": {
                "operationId": "get-coupons",
                "summary": "The coupons that can be applied",
                "description": "The shop's published coupons, so an operator can pick one rather than remember a code. Applying it\nis a separate call, and the shop validates it again there: a coupon listed here can still be\nrefused for this particular order.",
                "tags": [
                    "coupons"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "read"
                ],
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "code": {
                                                        "type": "string",
                                                        "description": "What the customer would type. This is what you send to apply it."
                                                    },
                                                    "flat_amount": {
                                                        "type": "number",
                                                        "description": "A fixed reduction, `0` when the coupon is a percentage."
                                                    },
                                                    "percent_amount": {
                                                        "type": "number",
                                                        "description": "A percentage reduction, `0` when the coupon is a fixed amount."
                                                    },
                                                    "currency_id": {
                                                        "type": "integer",
                                                        "description": "The currency a flat amount is expressed in."
                                                    },
                                                    "start": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Unix timestamp before which it is not valid."
                                                    },
                                                    "end": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ],
                                                        "description": "Unix timestamp after which it expires."
                                                    },
                                                    "quota": {
                                                        "type": "integer",
                                                        "description": "How many times it may be used in total, `0` for no limit."
                                                    },
                                                    "used_times": {
                                                        "type": "integer",
                                                        "description": "How many times it already has been."
                                                    },
                                                    "minimum_order": {
                                                        "type": "number",
                                                        "description": "The order total below which it does not apply, `0` for none."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/orders/{id}/status": {
            "post": {
                "operationId": "post-orders-id-status",
                "summary": "Change an order's status",
                "description": "Moves the order and, when asked, sends the customer the same notification the backend would have\nsent.\n\nThis calls the same code the backend does, so stock, invoices and every plugin listening on a\nstatus change behave exactly as they do there. It is not a database update.",
                "tags": [
                    "orders"
                ],
                "x-since": "6.6.0",
                "x-scopes": [
                    "write"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The order id.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "status": {
                                        "type": "string",
                                        "description": "A status **namekey**, as listed by `GET /statuses`. Not the translated label."
                                    },
                                    "notify": {
                                        "type": "boolean",
                                        "description": "Send the customer the notification for the new status. Defaults to `false`."
                                    },
                                    "reason": {
                                        "type": "string",
                                        "description": "Recorded in the order history, and included in the notification when there is one."
                                    }
                                },
                                "required": [
                                    "status"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The envelope, with the payload in data.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The order id."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "The namekey the order now has."
                                                },
                                                "changed": {
                                                    "type": "boolean",
                                                    "description": "False when the order already had that status."
                                                },
                                                "notified": {
                                                    "type": "boolean",
                                                    "description": "Whether the customer was actually emailed, which can be false even when you asked, if the status has no notification configured."
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": [
                                                "object",
                                                "null"
                                            ]
                                        },
                                        "error": {
                                            "type": "null"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "invalid_status: No such status namekey on this shop.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "not_found: No such order, or the operator may not see it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "save_failed: The order could not be saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
