{"components":{"responses":{},"schemas":{},"securitySchemes":{"bearer":{"scheme":"bearer","type":"http"}}},"info":{"description":"## Getting started\n\nWelcome to the Dotb API. Use it to prepare Vinted listings for import — create pending items and upload their photos, then import them into Vinted through the Dotb browser extension — and to access your Vinted orders for shipping and accounting. It also lets you look up the Vinted reference data needed to build a listing (catalogs, brands, colors, sizes, video game ratings) and read your Vinted accounts.\n\n> Requires a **Boutique AI** plan.\n\n## Authentication\n\nPass your API token as a Bearer token in the `Authorization` header.\n\n## Rate limits\n\nRate limits apply **per API token** (not per user), so each token gets its own allowance:\n\n- **60 requests per minute**\n- **10,000 requests per day**\n\nEvery response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers. When a limit is exceeded the API responds with `429 Too Many Requests` and a `Retry-After` header (in seconds).\n\n## For AI agents\n\nThis API is also available as LLM-friendly Markdown you can hand to an AI:\n\n- [llms.txt](/api/public/v1/llms.txt) — the full API for LLMs\n- [openapi.json](/api/public/v1/openapi.json) — the machine-readable spec\n","title":"Dotb Public API","version":"1"},"openapi":"3.0.0","paths":{"/api/public/v1/accounts":{"get":{"callbacks":{},"description":"Returns the Vinted accounts connected to the authenticated user.","operationId":"DotbWeb.Api.Public.V1.AccountsController.index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"bridge":{"description":"State of the browser extension's bridge for this account.","properties":{"connected":{"description":"true when a publish-capable extension is live on this account right now — i.e. a scheduled publish for it will be accepted.","type":"boolean"},"last_seen_at":{"description":"When the extension was last seen on the bridge (UTC), whether or not it is connected now. Held in memory, so it is null for an account that has not polled since the last server restart.","format":"date-time","nullable":true,"type":"string"}},"type":"object"},"country":{"nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"login":{"type":"string"},"vinted_id":{"type":"integer"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"List of accounts"}},"summary":"List Vinted accounts","tags":["Accounts"]}},"/api/public/v1/catalogs":{"get":{"callbacks":{},"description":"Returns the Vinted catalog tree up to a given depth for the resolved country. Responses are publicly cacheable for 1 hour.","operationId":"DotbWeb.Api.Public.V1.CatalogsController.index","parameters":[{"description":"ISO 3166-1 alpha-2 country code (e.g. \"FR\"). Inferred from account when omitted.","in":"query","name":"country","required":false,"schema":{"maxLength":2,"minLength":2,"type":"string"}},{"description":"Maximum tree depth to return (0–6, default 2).","in":"query","name":"depth","required":false,"schema":{"maximum":6,"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"depth":{"type":"integer"},"id":{"description":"Vinted catalog id.","type":"integer"},"parent_id":{"nullable":true,"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"List of catalogs"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Missing country"}},"summary":"List catalogs","tags":["Catalogs"]}},"/api/public/v1/catalogs/{catalog_id}":{"get":{"callbacks":{},"description":"Returns a single catalog by its Vinted id along with its ancestor breadcrumb.","operationId":"DotbWeb.Api.Public.V1.CatalogsController.show","parameters":[{"description":"Vinted catalog id (integer).","in":"path","name":"catalog_id","required":true,"schema":{"type":"integer"}},{"description":"ISO 3166-1 alpha-2 country code. Inferred from account when omitted.","in":"query","name":"country","required":false,"schema":{"maxLength":2,"minLength":2,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"ancestors":{"items":{"properties":{"id":{"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"catalog":{"properties":{"depth":{"type":"integer"},"id":{"description":"Vinted catalog id.","type":"integer"},"parent_id":{"nullable":true,"type":"integer"},"title":{"type":"string"}},"type":"object"}},"type":"object"}}},"description":"Catalog with ancestors"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found"}},"summary":"Get catalog","tags":["Catalogs"]}},"/api/public/v1/catalogs/{catalog_id}/brands/{brand_id}/models":{"get":{"callbacks":{},"description":"Returns the model picker for a catalog + brand pair — Vinted offers one for phones, tablets, laptops, headphones and some luxury bags. Send the picked row as the item's `model`: `{\"name\": row.name, \"metadata\": row.metadata}`. Most brands list flat models (iPhone 15 Pro); a few group them, listing a collection (Neverfull) and then its models (Neverfull MM) — either can be picked. GET /brands/with-models lists the pairs that have one; an empty list means the pair has none.","operationId":"DotbWeb.Api.Public.V1.CatalogsController.models","parameters":[{"description":"Vinted catalog id (integer).","in":"path","name":"catalog_id","required":true,"schema":{"type":"integer"}},{"description":"Vinted brand id (integer).","in":"path","name":"brand_id","required":true,"schema":{"type":"integer"}},{"description":"ISO 3166-1 alpha-2 country code. Inferred from account when omitted.","in":"query","name":"country","required":false,"schema":{"maxLength":2,"minLength":2,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"has_children":{"description":"Picking this row brings fields of its own — fetch them via the attributes endpoint.","type":"boolean"},"key":{"description":"Opaque row id, unique per row (e.g. \"4058\" or \"2233-2235\").","type":"string"},"metadata":{"description":"Send as is as the item's `model.metadata`. `model_id` is present only on a collection's models (\"Neverfull MM\"), not on flat models (\"iPhone 15 Pro\").","properties":{"collection_id":{"type":"integer"},"model_id":{"type":"integer"}},"required":["collection_id"],"type":"object"},"name":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"Brand models"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Missing country"}},"summary":"List brand models","tags":["Catalogs"]}},"/api/public/v1/catalogs/{catalog_id}/brands/{brand_id}/models/attributes":{"get":{"callbacks":{},"description":"Returns the extra fields a picked model brings with it (e.g. an iPhone's required `battery_health`), shaped like the `attributes` of the catalog options endpoint. Only needed for rows with `has_children: true`; send the answers in the item's `item_attributes`.","operationId":"DotbWeb.Api.Public.V1.CatalogsController.model_attributes","parameters":[{"description":"Vinted catalog id (integer).","in":"path","name":"catalog_id","required":true,"schema":{"type":"integer"}},{"description":"Vinted brand id (integer).","in":"path","name":"brand_id","required":true,"schema":{"type":"integer"}},{"description":"ISO 3166-1 alpha-2 country code. Inferred from account when omitted.","in":"query","name":"country","required":false,"schema":{"maxLength":2,"minLength":2,"type":"string"}},{"description":"The picked row's `metadata.collection_id`.","in":"query","name":"collection_id","required":true,"schema":{"type":"integer"}},{"description":"The picked row's `metadata.model_id`, when it has one.","in":"query","name":"model_id","required":false,"schema":{"type":"integer"}},{"description":"Language code for translated titles (e.g. \"en\"). Defaults to the country's language.","in":"query","name":"locale","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"code":{"type":"string"},"display_type":{"nullable":true,"type":"string"},"options":{"items":{"properties":{"id":{"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"required":{"type":"boolean"},"selection_limit":{"nullable":true,"type":"integer"},"selection_type":{"nullable":true,"type":"string"},"title":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"Model attributes"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Missing country"}},"summary":"Get model attributes","tags":["Catalogs"]}},"/api/public/v1/catalogs/{catalog_id}/options":{"get":{"callbacks":{},"description":"Returns the available conditions, package sizes, size groups, and attributes for a catalog — i.e. everything needed to render a listing form. When `parcel_measurements` is set, the catalog ships by measured parcel (snowboards, skis, power tools…): send the item's `parcel` instead of picking a `package_size_id`.","operationId":"DotbWeb.Api.Public.V1.CatalogsController.options","parameters":[{"description":"Vinted catalog id (integer).","in":"path","name":"catalog_id","required":true,"schema":{"type":"integer"}},{"description":"ISO 3166-1 alpha-2 country code. Inferred from account when omitted.","in":"query","name":"country","required":false,"schema":{"maxLength":2,"minLength":2,"type":"string"}},{"description":"BCP 47 locale code for translated titles. Defaults to the country's language.","in":"query","name":"locale","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"ancestors":{"items":{"properties":{"id":{"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"attributes":{"items":{"properties":{"code":{"type":"string"},"display_type":{"nullable":true,"type":"string"},"options":{"items":{"properties":{"id":{"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"required":{"type":"boolean"},"selection_limit":{"nullable":true,"type":"integer"},"selection_type":{"nullable":true,"type":"string"},"title":{"type":"string"}},"type":"object"},"type":"array"},"catalog":{"properties":{"depth":{"type":"integer"},"id":{"description":"Vinted catalog id.","type":"integer"},"parent_id":{"nullable":true,"type":"integer"},"title":{"type":"string"}},"type":"object"},"conditions":{"items":{"properties":{"explanation":{"type":"string"},"id":{"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"package_sizes":{"items":{"properties":{"description":{"type":"string"},"id":{"type":"integer"},"standard":{"type":"boolean"},"title":{"type":"string"}},"type":"object"},"type":"array"},"parcel_measurements":{"description":"Set when the catalog ships by measured parcel: the item needs a `parcel` (height, length, width, weight) and no `package_size_id`. Null otherwise.","nullable":true,"properties":{"dimension_unit":{"example":"cm","type":"string"},"limits":{"description":"Vinted's shipping limits for the parcel; POST/PATCH /items rejects a `parcel` that breaks one (422).","properties":{"max_side_cm":{"description":"Longest side, at most (cm).","example":100,"type":"integer"},"max_sides_sum_cm":{"description":"Height + length + width, at most (cm).","example":250,"type":"integer"},"weight_under_kg":{"description":"Weight must be strictly under this (kg).","example":31,"type":"number"}},"type":"object"},"suggested_weight":{"description":"Vinted's default weight for the catalog, to pre-fill.","example":3,"nullable":true,"type":"number"},"weight_unit":{"example":"kg","type":"string"}},"type":"object"},"size_groups":{"items":{"properties":{"id":{"type":"integer"},"sizes":{"items":{"properties":{"id":{"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"title":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"Catalog options"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found"}},"summary":"Get catalog form options","tags":["Catalogs"]}},"/api/public/v1/brands":{"get":{"callbacks":{},"description":"Full-text search over Vinted brands. The `q` query parameter is required.","operationId":"DotbWeb.Api.Public.V1.BrandsController.index","parameters":[{"description":"Search query (required, non-empty).","in":"query","name":"q","required":true,"schema":{"type":"string"}},{"description":"Maximum number of results (1–100, default 25).","in":"query","name":"limit","required":false,"schema":{"maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"id":{"description":"Vinted brand id.","type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"has_more":{"type":"boolean"},"next_cursor":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Brand search results"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Validation error (missing q)"}},"summary":"Search brands","tags":["Brands"]}},"/api/public/v1/brands/with-models":{"get":{"callbacks":{},"description":"Returns every brand Vinted offers a model picker for (phones, tablets, laptops, headphones, some luxury bags), each with the catalogs it has one in. For an item whose `catalog_id` is in a brand's `catalog_ids`, list the models via GET /catalogs/{catalog_id}/brands/{brand_id}/models and send the picked one as the item's `model`. Responses are publicly cacheable for 1 hour.","operationId":"DotbWeb.Api.Public.V1.BrandsController.with_models","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"catalog_ids":{"description":"Vinted catalog ids where this brand has a model picker.","items":{"type":"integer"},"type":"array"},"id":{"description":"Vinted brand id.","type":"integer"},"title":{"nullable":true,"type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"Brands with a model picker"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"}},"summary":"List brands with a model picker","tags":["Brands"]}},"/api/public/v1/colors":{"get":{"callbacks":{},"description":"Returns all Vinted colors. Titles are localized to the language of the given `country` (defaults to English). Responses are publicly cacheable for 1 hour.","operationId":"DotbWeb.Api.Public.V1.ColorsController.index","parameters":[{"description":"ISO 3166-1 alpha-2 country code (e.g. \"FR\") used to localize titles. Defaults to English when omitted or unknown.","in":"query","name":"country","required":false,"schema":{"maxLength":2,"minLength":2,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"code":{"example":"black","nullable":true,"type":"string"},"hex":{"example":"#000000","nullable":true,"type":"string"},"id":{"description":"Vinted color id.","type":"integer"},"title":{"example":"Black","type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"List of colors"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"}},"summary":"List colors","tags":["Colors"]}},"/api/public/v1/video-game-ratings":{"get":{"callbacks":{},"description":"Returns all Vinted video game ratings (e.g. PEGI 3, PEGI 7). Titles are localized to the language of the given `country` (defaults to English). Responses are publicly cacheable for 1 hour.","operationId":"DotbWeb.Api.Public.V1.VideoGameRatingsController.index","parameters":[{"description":"ISO 3166-1 alpha-2 country code (e.g. \"FR\") used to localize titles. Defaults to English when omitted or unknown.","in":"query","name":"country","required":false,"schema":{"maxLength":2,"minLength":2,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"properties":{"id":{"description":"Vinted video game rating id.","type":"integer"},"title":{"example":"PEGI 3","type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"List of video game ratings"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"}},"summary":"List video game ratings","tags":["Video game ratings"]}},"/api/public/v1/items":{"get":{"callbacks":{},"description":"Returns the authenticated user's Vinted items with keyset pagination.","operationId":"DotbWeb.Api.Public.V1.ItemsController.index","parameters":[{"description":"Filter by import status: pending (default), imported, or all.","in":"query","name":"status","required":false,"schema":{"enum":["pending","imported","all"],"type":"string"}},{"description":"Restrict results to a specific Vinted account UUID.","in":"query","name":"account_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Page size (1–100, default 25).","in":"query","name":"limit","required":false,"schema":{"maximum":100,"minimum":1,"type":"integer"}},{"description":"Opaque keyset cursor from a previous response's `next_cursor`.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"description":"A Vinted item managed through Dotb. Fields fall into two groups:\n\n**Vinted fields** — map onto Vinted's own listing payload: `title`, `description`,\n`price`, `currency`, `brand_id`, `brand`, `catalog_id`, `size_id`, `status_id`,\n`color_ids`, `package_size_id`, `isbn`, `is_unisex`, `item_attributes`,\n`video_game_rating_id`, `disposal_conditions`, `measurement_length`,\n`measurement_width`, `manufacturer`, `manufacturer_labelling`, `model`, `parcel`, plus the\nread-only `vinted_id`.\n\n**Dotb fields** — used by Dotb's inventory/automation layer, never sent to Vinted:\n`vinted_account_id`, `sku`, `location`, `purchase_price`, `messages_enabled`,\n`accept_offers_enabled`, `minimum_offer_price`, `counter_offer_price`,\n`supplier_link`, `restock_enabled`, `restock_quantity`, plus the read-only\n`id`, `status`, `photos`, `scheduled_publish_at`.\n","properties":{"catalog_id":{"nullable":true,"type":"integer"},"size_id":{"nullable":true,"type":"integer"},"location":{"nullable":true,"type":"string"},"parcel":{"description":"Measured parcel, for a catalog whose GET /catalogs/{catalog_id}/options returns `parcel_measurements` (snowboards, skis, power tools…). Those catalogs have no package size to pick: leave `package_size_id` empty and Vinted derives it from the parcel when the extension publishes. Centimetres and kilograms. On PATCH it replaces the stored parcel whole.","nullable":true,"properties":{"dimensions":{"properties":{"height":{"description":"Height in cm.","example":10,"type":"number"},"length":{"description":"Length in cm.","example":100,"type":"number"},"width":{"description":"Width in cm.","example":25,"type":"number"}},"required":["height","length","width"],"type":"object"},"weight":{"description":"Weight in kg.","example":4,"type":"number"}},"required":["dimensions","weight"],"type":"object"},"minimum_offer_price":{"example":"20.00","nullable":true,"type":"string"},"isbn":{"nullable":true,"type":"string"},"vinted_account_id":{"format":"uuid","type":"string"},"sku":{"nullable":true,"type":"string"},"item_attributes":{"items":{"type":"object"},"type":"array"},"status_id":{"nullable":true,"type":"integer"},"manufacturer":{"nullable":true,"type":"string"},"disposal_conditions":{"type":"boolean"},"scheduled_publish_at":{"description":"When this item is due to publish to Vinted, or null if no publish is pending. Set via POST /items/:id/schedule.","format":"date-time","nullable":true,"type":"string"},"status":{"enum":["pending","imported"],"type":"string"},"is_unisex":{"nullable":true,"type":"boolean"},"description":{"nullable":true,"type":"string"},"accept_offers_enabled":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"brand_id":{"nullable":true,"type":"integer"},"counter_offer_price":{"example":"25.00","nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"price":{"example":"29.90","nullable":true,"type":"string"},"model":{"description":"Model picked for a catalog + brand that has a model picker (see GET /catalogs/{catalog_id}/brands/{brand_id}/models). Pass `metadata` with the row's `collection_id` and `model_id` (when set). `collection_id` 1 means \"I don't know the model\"; 2 means \"my model isn't listed\", with the model's name in `suggestion`.","nullable":true,"properties":{"metadata":{"properties":{"collection_id":{"type":"integer"},"model_id":{"nullable":true,"type":"integer"}},"required":["collection_id"],"type":"object"},"name":{"description":"Display name of the picked row.","type":"string"},"suggestion":{"description":"Free-text model name, with collection_id 2.","type":"string"}},"type":"object"},"photos":{"items":{"properties":{"image_no":{"type":"integer"},"url":{"nullable":true,"type":"string"}},"type":"object"},"type":"array"},"restock_quantity":{"nullable":true,"type":"integer"},"manufacturer_labelling":{"nullable":true,"type":"string"},"brand":{"nullable":true,"type":"string"},"video_game_rating_id":{"nullable":true,"type":"integer"},"restock_enabled":{"nullable":true,"type":"boolean"},"measurement_length":{"nullable":true,"type":"integer"},"measurement_width":{"nullable":true,"type":"integer"},"messages_enabled":{"type":"boolean"},"package_size_id":{"nullable":true,"type":"integer"},"supplier_link":{"nullable":true,"type":"string"},"color_ids":{"items":{"type":"integer"},"type":"array"},"vinted_id":{"nullable":true,"type":"integer"},"title":{"nullable":true,"type":"string"}},"type":"object"},"type":"array"},"has_more":{"type":"boolean"},"next_cursor":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Paginated list of items"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"}},"summary":"List items","tags":["Items"]},"post":{"callbacks":{},"description":"Creates a pending (source: dotb) item for the authenticated user. Photos are not part of this request; upload them afterwards via POST /items/:id/photos.","operationId":"DotbWeb.Api.Public.V1.ItemsController.create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"description":"Vinted-native fields — map onto Vinted's listing payload.","properties":{"brand":{"description":"Brand name for a new/custom brand. For an existing Vinted brand pass brand_id instead (look it up via GET /brands); the API fills the name automatically.","nullable":true,"type":"string"},"brand_id":{"description":"Existing Vinted brand id (look it up via GET /brands). Takes priority over `brand` — the canonical name is resolved and returned automatically. To create an item with no brand, pass the special `brand_id` 1 (\"no_brand\").","nullable":true,"type":"integer"},"catalog_id":{"description":"Vinted catalog (category) id.","type":"integer"},"color_ids":{"description":"Up to 2 Vinted color ids.","items":{"type":"integer"},"type":"array"},"currency":{"description":"ISO 4217 currency code.","example":"EUR","type":"string"},"description":{"description":"Item description (5–2000 chars).","maxLength":2000,"minLength":5,"type":"string"},"disposal_conditions":{"description":"Disposal conditions acknowledgement.","nullable":true,"type":"boolean"},"is_unisex":{"description":"Unisex flag.","nullable":true,"type":"boolean"},"isbn":{"description":"ISBN (books/media).","nullable":true,"type":"string"},"item_attributes":{"description":"Catalog-specific attribute selections, with option ids from the catalog's `attributes` in GET /catalogs/{catalog_id}/options. Skirts (catalog 5523) require `skirt_length`: Vinted neither drafts nor publishes a skirt without it, so a missing or unknown one is rejected with 422. On PATCH the array replaces the stored one whole.","items":{"properties":{"code":{"example":"skirt_length","type":"string"},"ids":{"example":[392],"items":{"type":"integer"},"type":"array"}},"type":"object"},"type":"array"},"manufacturer":{"description":"Manufacturer.","nullable":true,"type":"string"},"manufacturer_labelling":{"description":"Manufacturer labelling info.","nullable":true,"type":"string"},"measurement_length":{"description":"Length (cm).","nullable":true,"type":"integer"},"measurement_width":{"description":"Width (cm).","nullable":true,"type":"integer"},"model":{"description":"Model picked for a catalog + brand that has a model picker (see GET /catalogs/{catalog_id}/brands/{brand_id}/models). Pass `metadata` with the row's `collection_id` and `model_id` (when set). `collection_id` 1 means \"I don't know the model\"; 2 means \"my model isn't listed\", with the model's name in `suggestion`.","nullable":true,"properties":{"metadata":{"properties":{"collection_id":{"type":"integer"},"model_id":{"nullable":true,"type":"integer"}},"required":["collection_id"],"type":"object"},"name":{"description":"Display name of the picked row.","type":"string"},"suggestion":{"description":"Free-text model name, with collection_id 2.","type":"string"}},"type":"object"},"package_size_id":{"description":"Vinted package size id.","nullable":true,"type":"integer"},"parcel":{"description":"Measured parcel, for a catalog whose GET /catalogs/{catalog_id}/options returns `parcel_measurements` (snowboards, skis, power tools…). Those catalogs have no package size to pick: leave `package_size_id` empty and Vinted derives it from the parcel when the extension publishes. Centimetres and kilograms. On PATCH it replaces the stored parcel whole.","nullable":true,"properties":{"dimensions":{"properties":{"height":{"description":"Height in cm.","example":10,"type":"number"},"length":{"description":"Length in cm.","example":100,"type":"number"},"width":{"description":"Width in cm.","example":25,"type":"number"}},"required":["height","length","width"],"type":"object"},"weight":{"description":"Weight in kg.","example":4,"type":"number"}},"required":["dimensions","weight"],"type":"object"},"price":{"description":"Listing price as a decimal string.","example":"29.90","type":"string"},"size_id":{"description":"Vinted size id.","nullable":true,"type":"integer"},"status_id":{"description":"Vinted condition id.","nullable":true,"type":"integer"},"title":{"description":"Item title (5–100 chars, max 6 non-title-case capital letters).","maxLength":100,"minLength":5,"type":"string"},"video_game_rating_id":{"description":"Vinted video game rating id (see /video-game-ratings).","nullable":true,"type":"integer"}},"type":"object"},{"description":"Dotb-only fields — inventory/automation, not sent to Vinted.","properties":{"accept_offers_enabled":{"description":"Allow buyers to make offers.","type":"boolean"},"counter_offer_price":{"description":"Counter-offer price.","example":"25.00","nullable":true,"type":"string"},"location":{"description":"Free-text storage location.","nullable":true,"type":"string"},"messages_enabled":{"description":"Allow buyers to send messages.","type":"boolean"},"minimum_offer_price":{"description":"Minimum acceptable offer price.","example":"20.00","nullable":true,"type":"string"},"purchase_price":{"description":"Your cost price (not shown to buyers).","example":"15.00","nullable":true,"type":"string"},"restock_enabled":{"description":"Enable auto-restock (relist after sale).","nullable":true,"type":"boolean"},"restock_quantity":{"description":"Remaining restock count (-1 = unlimited, range -1..32767).","example":3,"nullable":true,"type":"integer"},"sku":{"description":"Your internal SKU.","nullable":true,"type":"string"},"supplier_link":{"description":"URL of the item's supplier/source (https:// is prepended when no scheme is given).","example":"https://example.com/product/123","nullable":true,"type":"string"},"vinted_account_id":{"description":"UUID of the Vinted account on Dotb to associate the item with.","format":"uuid","type":"string"}},"type":"object"}],"required":["vinted_account_id","title","description","price","currency","catalog_id"]}}},"description":"Item attributes","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"description":"A Vinted item managed through Dotb. Fields fall into two groups:\n\n**Vinted fields** — map onto Vinted's own listing payload: `title`, `description`,\n`price`, `currency`, `brand_id`, `brand`, `catalog_id`, `size_id`, `status_id`,\n`color_ids`, `package_size_id`, `isbn`, `is_unisex`, `item_attributes`,\n`video_game_rating_id`, `disposal_conditions`, `measurement_length`,\n`measurement_width`, `manufacturer`, `manufacturer_labelling`, `model`, `parcel`, plus the\nread-only `vinted_id`.\n\n**Dotb fields** — used by Dotb's inventory/automation layer, never sent to Vinted:\n`vinted_account_id`, `sku`, `location`, `purchase_price`, `messages_enabled`,\n`accept_offers_enabled`, `minimum_offer_price`, `counter_offer_price`,\n`supplier_link`, `restock_enabled`, `restock_quantity`, plus the read-only\n`id`, `status`, `photos`, `scheduled_publish_at`.\n","properties":{"catalog_id":{"nullable":true,"type":"integer"},"size_id":{"nullable":true,"type":"integer"},"location":{"nullable":true,"type":"string"},"parcel":{"description":"Measured parcel, for a catalog whose GET /catalogs/{catalog_id}/options returns `parcel_measurements` (snowboards, skis, power tools…). Those catalogs have no package size to pick: leave `package_size_id` empty and Vinted derives it from the parcel when the extension publishes. Centimetres and kilograms. On PATCH it replaces the stored parcel whole.","nullable":true,"properties":{"dimensions":{"properties":{"height":{"description":"Height in cm.","example":10,"type":"number"},"length":{"description":"Length in cm.","example":100,"type":"number"},"width":{"description":"Width in cm.","example":25,"type":"number"}},"required":["height","length","width"],"type":"object"},"weight":{"description":"Weight in kg.","example":4,"type":"number"}},"required":["dimensions","weight"],"type":"object"},"minimum_offer_price":{"example":"20.00","nullable":true,"type":"string"},"isbn":{"nullable":true,"type":"string"},"vinted_account_id":{"format":"uuid","type":"string"},"sku":{"nullable":true,"type":"string"},"item_attributes":{"items":{"type":"object"},"type":"array"},"status_id":{"nullable":true,"type":"integer"},"manufacturer":{"nullable":true,"type":"string"},"disposal_conditions":{"type":"boolean"},"scheduled_publish_at":{"description":"When this item is due to publish to Vinted, or null if no publish is pending. Set via POST /items/:id/schedule.","format":"date-time","nullable":true,"type":"string"},"status":{"enum":["pending","imported"],"type":"string"},"is_unisex":{"nullable":true,"type":"boolean"},"description":{"nullable":true,"type":"string"},"accept_offers_enabled":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"brand_id":{"nullable":true,"type":"integer"},"counter_offer_price":{"example":"25.00","nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"price":{"example":"29.90","nullable":true,"type":"string"},"model":{"description":"Model picked for a catalog + brand that has a model picker (see GET /catalogs/{catalog_id}/brands/{brand_id}/models). Pass `metadata` with the row's `collection_id` and `model_id` (when set). `collection_id` 1 means \"I don't know the model\"; 2 means \"my model isn't listed\", with the model's name in `suggestion`.","nullable":true,"properties":{"metadata":{"properties":{"collection_id":{"type":"integer"},"model_id":{"nullable":true,"type":"integer"}},"required":["collection_id"],"type":"object"},"name":{"description":"Display name of the picked row.","type":"string"},"suggestion":{"description":"Free-text model name, with collection_id 2.","type":"string"}},"type":"object"},"photos":{"items":{"properties":{"image_no":{"type":"integer"},"url":{"nullable":true,"type":"string"}},"type":"object"},"type":"array"},"restock_quantity":{"nullable":true,"type":"integer"},"manufacturer_labelling":{"nullable":true,"type":"string"},"brand":{"nullable":true,"type":"string"},"video_game_rating_id":{"nullable":true,"type":"integer"},"restock_enabled":{"nullable":true,"type":"boolean"},"measurement_length":{"nullable":true,"type":"integer"},"measurement_width":{"nullable":true,"type":"integer"},"messages_enabled":{"type":"boolean"},"package_size_id":{"nullable":true,"type":"integer"},"supplier_link":{"nullable":true,"type":"string"},"color_ids":{"items":{"type":"integer"},"type":"array"},"vinted_id":{"nullable":true,"type":"integer"},"title":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Created item"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Account not found / not owned"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Validation error"}},"summary":"Create item","tags":["Items"]}},"/api/public/v1/items/{id}":{"get":{"callbacks":{},"description":"Returns a single item by id. Returns 404 if the item belongs to another user.","operationId":"DotbWeb.Api.Public.V1.ItemsController.show","parameters":[{"description":"Item UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"A Vinted item managed through Dotb. Fields fall into two groups:\n\n**Vinted fields** — map onto Vinted's own listing payload: `title`, `description`,\n`price`, `currency`, `brand_id`, `brand`, `catalog_id`, `size_id`, `status_id`,\n`color_ids`, `package_size_id`, `isbn`, `is_unisex`, `item_attributes`,\n`video_game_rating_id`, `disposal_conditions`, `measurement_length`,\n`measurement_width`, `manufacturer`, `manufacturer_labelling`, `model`, `parcel`, plus the\nread-only `vinted_id`.\n\n**Dotb fields** — used by Dotb's inventory/automation layer, never sent to Vinted:\n`vinted_account_id`, `sku`, `location`, `purchase_price`, `messages_enabled`,\n`accept_offers_enabled`, `minimum_offer_price`, `counter_offer_price`,\n`supplier_link`, `restock_enabled`, `restock_quantity`, plus the read-only\n`id`, `status`, `photos`, `scheduled_publish_at`.\n","properties":{"catalog_id":{"nullable":true,"type":"integer"},"size_id":{"nullable":true,"type":"integer"},"location":{"nullable":true,"type":"string"},"parcel":{"description":"Measured parcel, for a catalog whose GET /catalogs/{catalog_id}/options returns `parcel_measurements` (snowboards, skis, power tools…). Those catalogs have no package size to pick: leave `package_size_id` empty and Vinted derives it from the parcel when the extension publishes. Centimetres and kilograms. On PATCH it replaces the stored parcel whole.","nullable":true,"properties":{"dimensions":{"properties":{"height":{"description":"Height in cm.","example":10,"type":"number"},"length":{"description":"Length in cm.","example":100,"type":"number"},"width":{"description":"Width in cm.","example":25,"type":"number"}},"required":["height","length","width"],"type":"object"},"weight":{"description":"Weight in kg.","example":4,"type":"number"}},"required":["dimensions","weight"],"type":"object"},"minimum_offer_price":{"example":"20.00","nullable":true,"type":"string"},"isbn":{"nullable":true,"type":"string"},"vinted_account_id":{"format":"uuid","type":"string"},"sku":{"nullable":true,"type":"string"},"item_attributes":{"items":{"type":"object"},"type":"array"},"status_id":{"nullable":true,"type":"integer"},"manufacturer":{"nullable":true,"type":"string"},"disposal_conditions":{"type":"boolean"},"scheduled_publish_at":{"description":"When this item is due to publish to Vinted, or null if no publish is pending. Set via POST /items/:id/schedule.","format":"date-time","nullable":true,"type":"string"},"status":{"enum":["pending","imported"],"type":"string"},"is_unisex":{"nullable":true,"type":"boolean"},"description":{"nullable":true,"type":"string"},"accept_offers_enabled":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"brand_id":{"nullable":true,"type":"integer"},"counter_offer_price":{"example":"25.00","nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"price":{"example":"29.90","nullable":true,"type":"string"},"model":{"description":"Model picked for a catalog + brand that has a model picker (see GET /catalogs/{catalog_id}/brands/{brand_id}/models). Pass `metadata` with the row's `collection_id` and `model_id` (when set). `collection_id` 1 means \"I don't know the model\"; 2 means \"my model isn't listed\", with the model's name in `suggestion`.","nullable":true,"properties":{"metadata":{"properties":{"collection_id":{"type":"integer"},"model_id":{"nullable":true,"type":"integer"}},"required":["collection_id"],"type":"object"},"name":{"description":"Display name of the picked row.","type":"string"},"suggestion":{"description":"Free-text model name, with collection_id 2.","type":"string"}},"type":"object"},"photos":{"items":{"properties":{"image_no":{"type":"integer"},"url":{"nullable":true,"type":"string"}},"type":"object"},"type":"array"},"restock_quantity":{"nullable":true,"type":"integer"},"manufacturer_labelling":{"nullable":true,"type":"string"},"brand":{"nullable":true,"type":"string"},"video_game_rating_id":{"nullable":true,"type":"integer"},"restock_enabled":{"nullable":true,"type":"boolean"},"measurement_length":{"nullable":true,"type":"integer"},"measurement_width":{"nullable":true,"type":"integer"},"messages_enabled":{"type":"boolean"},"package_size_id":{"nullable":true,"type":"integer"},"supplier_link":{"nullable":true,"type":"string"},"color_ids":{"items":{"type":"integer"},"type":"array"},"vinted_id":{"nullable":true,"type":"integer"},"title":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Item"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found"}},"summary":"Get item","tags":["Items"]},"patch":{"callbacks":{},"description":"Updates a pending (dotb-created) item. Only items without a vinted_id are editable; imported items return 404. Merges data fields. Photos are managed separately via POST /items/:id/photos.","operationId":"DotbWeb.Api.Public.V1.ItemsController.update","parameters":[{"description":"Item UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"description":"Vinted-native fields — map onto Vinted's listing payload.","properties":{"brand":{"description":"Brand name for a new/custom brand. For an existing Vinted brand pass brand_id instead (look it up via GET /brands); the API fills the name automatically.","nullable":true,"type":"string"},"brand_id":{"description":"Existing Vinted brand id (look it up via GET /brands). Takes priority over `brand` — the canonical name is resolved and returned automatically. To create an item with no brand, pass the special `brand_id` 1 (\"no_brand\").","nullable":true,"type":"integer"},"catalog_id":{"description":"Vinted catalog (category) id.","type":"integer"},"color_ids":{"description":"Up to 2 Vinted color ids.","items":{"type":"integer"},"type":"array"},"currency":{"description":"ISO 4217 currency code.","example":"EUR","type":"string"},"description":{"description":"Item description (5–2000 chars).","maxLength":2000,"minLength":5,"type":"string"},"disposal_conditions":{"description":"Disposal conditions acknowledgement.","nullable":true,"type":"boolean"},"is_unisex":{"description":"Unisex flag.","nullable":true,"type":"boolean"},"isbn":{"description":"ISBN (books/media).","nullable":true,"type":"string"},"item_attributes":{"description":"Catalog-specific attribute selections, with option ids from the catalog's `attributes` in GET /catalogs/{catalog_id}/options. Skirts (catalog 5523) require `skirt_length`: Vinted neither drafts nor publishes a skirt without it, so a missing or unknown one is rejected with 422. On PATCH the array replaces the stored one whole.","items":{"properties":{"code":{"example":"skirt_length","type":"string"},"ids":{"example":[392],"items":{"type":"integer"},"type":"array"}},"type":"object"},"type":"array"},"manufacturer":{"description":"Manufacturer.","nullable":true,"type":"string"},"manufacturer_labelling":{"description":"Manufacturer labelling info.","nullable":true,"type":"string"},"measurement_length":{"description":"Length (cm).","nullable":true,"type":"integer"},"measurement_width":{"description":"Width (cm).","nullable":true,"type":"integer"},"model":{"description":"Model picked for a catalog + brand that has a model picker (see GET /catalogs/{catalog_id}/brands/{brand_id}/models). Pass `metadata` with the row's `collection_id` and `model_id` (when set). `collection_id` 1 means \"I don't know the model\"; 2 means \"my model isn't listed\", with the model's name in `suggestion`.","nullable":true,"properties":{"metadata":{"properties":{"collection_id":{"type":"integer"},"model_id":{"nullable":true,"type":"integer"}},"required":["collection_id"],"type":"object"},"name":{"description":"Display name of the picked row.","type":"string"},"suggestion":{"description":"Free-text model name, with collection_id 2.","type":"string"}},"type":"object"},"package_size_id":{"description":"Vinted package size id.","nullable":true,"type":"integer"},"parcel":{"description":"Measured parcel, for a catalog whose GET /catalogs/{catalog_id}/options returns `parcel_measurements` (snowboards, skis, power tools…). Those catalogs have no package size to pick: leave `package_size_id` empty and Vinted derives it from the parcel when the extension publishes. Centimetres and kilograms. On PATCH it replaces the stored parcel whole.","nullable":true,"properties":{"dimensions":{"properties":{"height":{"description":"Height in cm.","example":10,"type":"number"},"length":{"description":"Length in cm.","example":100,"type":"number"},"width":{"description":"Width in cm.","example":25,"type":"number"}},"required":["height","length","width"],"type":"object"},"weight":{"description":"Weight in kg.","example":4,"type":"number"}},"required":["dimensions","weight"],"type":"object"},"price":{"description":"Listing price as a decimal string.","example":"29.90","type":"string"},"size_id":{"description":"Vinted size id.","nullable":true,"type":"integer"},"status_id":{"description":"Vinted condition id.","nullable":true,"type":"integer"},"title":{"description":"Item title (5–100 chars, max 6 non-title-case capital letters).","maxLength":100,"minLength":5,"type":"string"},"video_game_rating_id":{"description":"Vinted video game rating id (see /video-game-ratings).","nullable":true,"type":"integer"}},"type":"object"},{"description":"Dotb-only fields — inventory/automation, not sent to Vinted.","properties":{"accept_offers_enabled":{"description":"Allow buyers to make offers.","type":"boolean"},"counter_offer_price":{"description":"Counter-offer price.","example":"25.00","nullable":true,"type":"string"},"location":{"description":"Free-text storage location.","nullable":true,"type":"string"},"messages_enabled":{"description":"Allow buyers to send messages.","type":"boolean"},"minimum_offer_price":{"description":"Minimum acceptable offer price.","example":"20.00","nullable":true,"type":"string"},"purchase_price":{"description":"Your cost price (not shown to buyers).","example":"15.00","nullable":true,"type":"string"},"restock_enabled":{"description":"Enable auto-restock (relist after sale).","nullable":true,"type":"boolean"},"restock_quantity":{"description":"Remaining restock count (-1 = unlimited, range -1..32767).","example":3,"nullable":true,"type":"integer"},"sku":{"description":"Your internal SKU.","nullable":true,"type":"string"},"supplier_link":{"description":"URL of the item's supplier/source (https:// is prepended when no scheme is given).","example":"https://example.com/product/123","nullable":true,"type":"string"},"vinted_account_id":{"description":"UUID of the Vinted account on Dotb to associate the item with.","format":"uuid","type":"string"}},"type":"object"}]}}},"description":"Item attributes to update","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"description":"A Vinted item managed through Dotb. Fields fall into two groups:\n\n**Vinted fields** — map onto Vinted's own listing payload: `title`, `description`,\n`price`, `currency`, `brand_id`, `brand`, `catalog_id`, `size_id`, `status_id`,\n`color_ids`, `package_size_id`, `isbn`, `is_unisex`, `item_attributes`,\n`video_game_rating_id`, `disposal_conditions`, `measurement_length`,\n`measurement_width`, `manufacturer`, `manufacturer_labelling`, `model`, `parcel`, plus the\nread-only `vinted_id`.\n\n**Dotb fields** — used by Dotb's inventory/automation layer, never sent to Vinted:\n`vinted_account_id`, `sku`, `location`, `purchase_price`, `messages_enabled`,\n`accept_offers_enabled`, `minimum_offer_price`, `counter_offer_price`,\n`supplier_link`, `restock_enabled`, `restock_quantity`, plus the read-only\n`id`, `status`, `photos`, `scheduled_publish_at`.\n","properties":{"catalog_id":{"nullable":true,"type":"integer"},"size_id":{"nullable":true,"type":"integer"},"location":{"nullable":true,"type":"string"},"parcel":{"description":"Measured parcel, for a catalog whose GET /catalogs/{catalog_id}/options returns `parcel_measurements` (snowboards, skis, power tools…). Those catalogs have no package size to pick: leave `package_size_id` empty and Vinted derives it from the parcel when the extension publishes. Centimetres and kilograms. On PATCH it replaces the stored parcel whole.","nullable":true,"properties":{"dimensions":{"properties":{"height":{"description":"Height in cm.","example":10,"type":"number"},"length":{"description":"Length in cm.","example":100,"type":"number"},"width":{"description":"Width in cm.","example":25,"type":"number"}},"required":["height","length","width"],"type":"object"},"weight":{"description":"Weight in kg.","example":4,"type":"number"}},"required":["dimensions","weight"],"type":"object"},"minimum_offer_price":{"example":"20.00","nullable":true,"type":"string"},"isbn":{"nullable":true,"type":"string"},"vinted_account_id":{"format":"uuid","type":"string"},"sku":{"nullable":true,"type":"string"},"item_attributes":{"items":{"type":"object"},"type":"array"},"status_id":{"nullable":true,"type":"integer"},"manufacturer":{"nullable":true,"type":"string"},"disposal_conditions":{"type":"boolean"},"scheduled_publish_at":{"description":"When this item is due to publish to Vinted, or null if no publish is pending. Set via POST /items/:id/schedule.","format":"date-time","nullable":true,"type":"string"},"status":{"enum":["pending","imported"],"type":"string"},"is_unisex":{"nullable":true,"type":"boolean"},"description":{"nullable":true,"type":"string"},"accept_offers_enabled":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"brand_id":{"nullable":true,"type":"integer"},"counter_offer_price":{"example":"25.00","nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"price":{"example":"29.90","nullable":true,"type":"string"},"model":{"description":"Model picked for a catalog + brand that has a model picker (see GET /catalogs/{catalog_id}/brands/{brand_id}/models). Pass `metadata` with the row's `collection_id` and `model_id` (when set). `collection_id` 1 means \"I don't know the model\"; 2 means \"my model isn't listed\", with the model's name in `suggestion`.","nullable":true,"properties":{"metadata":{"properties":{"collection_id":{"type":"integer"},"model_id":{"nullable":true,"type":"integer"}},"required":["collection_id"],"type":"object"},"name":{"description":"Display name of the picked row.","type":"string"},"suggestion":{"description":"Free-text model name, with collection_id 2.","type":"string"}},"type":"object"},"photos":{"items":{"properties":{"image_no":{"type":"integer"},"url":{"nullable":true,"type":"string"}},"type":"object"},"type":"array"},"restock_quantity":{"nullable":true,"type":"integer"},"manufacturer_labelling":{"nullable":true,"type":"string"},"brand":{"nullable":true,"type":"string"},"video_game_rating_id":{"nullable":true,"type":"integer"},"restock_enabled":{"nullable":true,"type":"boolean"},"measurement_length":{"nullable":true,"type":"integer"},"measurement_width":{"nullable":true,"type":"integer"},"messages_enabled":{"type":"boolean"},"package_size_id":{"nullable":true,"type":"integer"},"supplier_link":{"nullable":true,"type":"string"},"color_ids":{"items":{"type":"integer"},"type":"array"},"vinted_id":{"nullable":true,"type":"integer"},"title":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Updated item"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found or not editable"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Validation error"}},"summary":"Update item","tags":["Items"]},"delete":{"callbacks":{},"description":"Permanently deletes a pending (dotb-created) item and its uploaded photos, and cancels any scheduled publish it still has. Only items without a vinted_id can be deleted; once an item is on Vinted it returns 404, because this endpoint cannot take the listing down from Vinted and deleting only the Dotb record would be misleading.","operationId":"DotbWeb.Api.Public.V1.ItemsController.delete","parameters":[{"description":"Item UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"id":{"format":"uuid","type":"string"},"status":{"enum":["deleted"],"type":"string"}},"type":"object"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found or already on Vinted"}},"summary":"Delete item","tags":["Items"]}},"/api/public/v1/items/{id}/photos":{"post":{"callbacks":{},"description":"Uploads a single image file (multipart/form-data, field `file`) and appends it to a pending item's photos. Call it once per photo. Only items without a vinted_id are editable; imported items return 404. Max file size is ~8MB (Plug.Parsers default).","operationId":"DotbWeb.Api.Public.V1.ItemPhotosController.create","parameters":[{"description":"Item UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"description":"The image file (jpeg/png/webp).","format":"binary","type":"string"}},"required":["file"],"type":"object"}}},"description":"Image file","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"description":"The updated item with its photos.","type":"object"}}},"description":"Item with the new photo"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Item not found or not editable"},"409":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Photo slot conflict; retry"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Missing file or unsupported content type"}},"summary":"Upload an item photo","tags":["Items"]}},"/api/public/v1/scheduled-publishes":{"get":{"callbacks":{},"description":"Returns the authenticated user's scheduled publishes — upcoming, running and finished — newest scheduled time first, with keyset pagination. History is pruned after 15 days.","operationId":"DotbWeb.Api.Public.V1.SchedulesController.index","parameters":[{"description":"Page size (1–100, default 25).","in":"query","name":"limit","required":false,"schema":{"maximum":100,"minimum":1,"type":"integer"}},{"description":"Opaque keyset cursor from a previous response's `next_cursor`.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"description":"One scheduled publish, upcoming or finished. `status` is:\n\n- `waiting` — queued, not started (includes jobs queued behind another publish on the same account)\n- `running` — publishing right now\n- `retrying` — a previous attempt failed and it will try again\n- `done` — published; `vinted_id` is the created listing\n- `failed` — gave up; see `error`\n- `cancelled` — cancelled before it ran\n- `draft_orphaned` — failed *after* the Vinted draft was created, so a draft exists on Vinted\n  (`vinted_id` is set) but the listing never went live\n","properties":{"attempt":{"type":"integer"},"error":{"description":"Present only on a failed attempt.","nullable":true,"properties":{"code":{"enum":["ai_photos","rejected","no_photos","missing_attributes","extension_offline","extension_error","account_restricted","validation","timeout","not_pending","server_error","unknown"],"type":"string"},"detail":{"nullable":true,"type":"string"}},"type":"object"},"finished_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"description":"Schedule id.","type":"string"},"item_id":{"format":"uuid","type":"string"},"max_attempts":{"type":"integer"},"publish":{"description":"true = go live, false = leave an unpublished Vinted draft.","type":"boolean"},"scheduled_at":{"format":"date-time","type":"string"},"status":{"enum":["waiting","running","retrying","done","failed","cancelled","draft_orphaned"],"type":"string"},"vinted_account_id":{"format":"uuid","type":"string"},"vinted_id":{"description":"Vinted listing id, once the draft exists.","nullable":true,"type":"integer"}},"type":"object"},"type":"array"},"has_more":{"type":"boolean"},"next_cursor":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Paginated list of scheduled publishes"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"}},"summary":"List scheduled publishes","tags":["Scheduled publishes"]}},"/api/public/v1/items/schedule":{"post":{"callbacks":{},"description":"Schedules up to 250 pending items in one call. Each entry carries its own\n`scheduled_at` and `publish` flag — the same payload `POST /items/{id}/schedule` takes, with\nthe id moved into the body — so you choose the spacing between publishes yourself.\n\nThere are two classes of failure, and they are deliberately different:\n\n- A **malformed request** is rejected whole with `422` and **nothing is scheduled** — `items`\n  missing, empty or over 250 entries, a duplicate `id`, a missing or\n  non-ISO-8601 `scheduled_at`, or a non-boolean `publish`.\n- A **per-item problem** does not fail the batch. The response is `200` with one row per\n  entry, in request order, and `scheduled_count` / `failed_count` summarising it. Check those\n  counts — an all-failed batch is still a `200`.\n\nSame rules as the single-item endpoint otherwise: only pending items (created through Dotb,\nnot yet on Vinted) can be scheduled, each item holds one schedule at a time, a connected\npublish-capable extension is required on the item's account at schedule time, and photos are\npublished as-is with no image processing.\n","operationId":"DotbWeb.Api.Public.V1.SchedulesController.bulk_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"properties":{"items":{"description":"One entry per item. Ids must be unique within the batch.","items":{"properties":{"id":{"description":"Item UUID.","format":"uuid","type":"string"},"publish":{"default":true,"description":"true (default) takes the listing live; false leaves an unpublished Vinted draft. Must be a real boolean, not a string.","type":"boolean"},"scheduled_at":{"description":"When to publish this item, ISO 8601 with a UTC offset. A past time publishes as soon as possible.","format":"date-time","type":"string"}},"required":["id","scheduled_at"],"type":"object"},"maxItems":250,"minItems":1,"type":"array"}},"required":["items"],"type":"object"}}},"description":"Items to schedule","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"failed_count":{"type":"integer"},"results":{"items":{"description":"One entry's outcome. `status` is `scheduled` or `failed`; on `failed`, `error.code` is:\n\n- `not_found` — not one of your pending items, or already on Vinted\n- `no_photos` — upload at least one photo first\n- `extension_offline` — no publish-capable extension on that item's Vinted account\n- `already_scheduled` — cancel the existing schedule first\n","properties":{"error":{"description":"Present only when `status` is `failed`.","nullable":true,"properties":{"code":{"enum":["not_found","no_photos","extension_offline","already_scheduled"],"type":"string"},"detail":{"type":"string"}},"type":"object"},"id":{"format":"uuid","type":"string"},"publish":{"nullable":true,"type":"boolean"},"scheduled_at":{"description":"When the publish will run (UTC). A past time is clamped to now.","format":"date-time","nullable":true,"type":"string"},"status":{"enum":["scheduled","failed"],"type":"string"},"vinted_account_id":{"format":"uuid","nullable":true,"type":"string"}},"type":"object"},"type":"array"},"scheduled_count":{"type":"integer"}},"type":"object"}}},"description":"Per-item outcome — check `failed_count`"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Malformed request — nothing was scheduled"}},"summary":"Schedule publishes in bulk","tags":["Scheduled publishes"]}},"/api/public/v1/items/{id}/schedule":{"post":{"callbacks":{},"description":"Queues a pending item to be published to Vinted at `scheduled_at`. The item's photos are\npublished as-is — this version applies no image processing.\n\nRequires a connected, publish-capable browser extension on the item's Vinted account; the\nschedule survives the extension going offline afterwards. Only pending items (created through\nDotb and not yet on Vinted) can be scheduled, and an item can hold one schedule at a time —\ncancel the existing one first.\n","operationId":"DotbWeb.Api.Public.V1.SchedulesController.create","parameters":[{"description":"Item UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"publish":{"default":true,"description":"true (default) takes the listing live; false leaves an unpublished Vinted draft.","type":"boolean"},"scheduled_at":{"description":"When to publish, ISO 8601 with a UTC offset. A past time publishes as soon as possible.","format":"date-time","type":"string"}},"required":["scheduled_at"],"type":"object"}}},"description":"Schedule attributes","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"description":"Confirmation that an item is queued to publish.","properties":{"item_id":{"format":"uuid","type":"string"},"publish":{"type":"boolean"},"scheduled_at":{"description":"When the publish will run (UTC). A past time is clamped to now.","format":"date-time","type":"string"},"status":{"enum":["scheduled","cancelled"],"type":"string"},"vinted_account_id":{"format":"uuid","type":"string"}},"type":"object"}}},"description":"Scheduled"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Item not found or not pending"},"409":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Extension offline, or already scheduled"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Validation error"}},"summary":"Schedule a publish","tags":["Scheduled publishes"]},"delete":{"callbacks":{},"description":"Cancels the item's pending schedule. Returns 404 when there is nothing to cancel — either it was never scheduled, or the publish has already started.","operationId":"DotbWeb.Api.Public.V1.SchedulesController.delete","parameters":[{"description":"Item UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"Confirmation that an item is queued to publish.","properties":{"item_id":{"format":"uuid","type":"string"},"publish":{"type":"boolean"},"scheduled_at":{"description":"When the publish will run (UTC). A past time is clamped to now.","format":"date-time","type":"string"},"status":{"enum":["scheduled","cancelled"],"type":"string"},"vinted_account_id":{"format":"uuid","type":"string"}},"type":"object"}}},"description":"Cancelled"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"No cancellable schedule"}},"summary":"Cancel a scheduled publish","tags":["Scheduled publishes"]}},"/api/public/v1/orders":{"get":{"callbacks":{},"description":"Returns the authenticated user's Vinted orders with keyset pagination.","operationId":"DotbWeb.Api.Public.V1.OrdersController.index","parameters":[{"description":"Filter by normalized_status. Invalid values are ignored.","in":"query","name":"status","required":false,"schema":{"enum":["payment_received","label_ordering","label_failed","label_sent","packed","shipped","ready_for_pickup","delivered","completed","returning","suspended","cancelled"],"type":"string"}},{"description":"Restrict results to a specific Vinted account UUID.","in":"query","name":"account_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Inclusive lower bound on order_date. Accepts a date (`YYYY-MM-DD`) or a full ISO8601 timestamp; a date-only value covers the whole day (from 00:00:00 UTC). Invalid values are ignored.","in":"query","name":"from","required":false,"schema":{"type":"string"}},{"description":"Inclusive upper bound on order_date. Accepts a date (`YYYY-MM-DD`) or a full ISO8601 timestamp; a date-only value covers the whole day (through 23:59:59 UTC). Invalid values are ignored.","in":"query","name":"to","required":false,"schema":{"type":"string"}},{"description":"Page size (1–100, default 25).","in":"query","name":"limit","required":false,"schema":{"maximum":100,"minimum":1,"type":"integer"}},{"description":"Opaque keyset cursor from a previous response's `next_cursor`. A cursor is bound to the `sort` it was created with — changing `sort` mid-pagination invalidates it, so restart from the first page (no cursor) whenever you change `sort`.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Comma-separated list of optional blocks to expand: `items`, `buyer`, `account`. Unknown tokens are ignored. Absent by default (lean response). Note: `shipping_address` and `shipping_label_url` are always-present base fields (not include-gated).","in":"query","name":"include","required":false,"schema":{"type":"string"}},{"description":"Sort column, with a fixed direction per column (no separate direction param). `order_date` (default) — newest first. `shipping_deadline_date` — soonest deadline first; orders without a deadline are always sorted last. Invalid/empty values fall back to `order_date`.","in":"query","name":"sort","required":false,"schema":{"enum":["order_date","shipping_deadline_date"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"description":"A Vinted order/transaction. Base fields are always present. This includes\n`shipping_label_url` (nullable — null until the label is fetched) and the buyer\n`shipping_address` block; both are always present, not gated behind any include.\n\nOptional blocks are present only when requested via `?include=` (comma-separated):\n\n- `items` — array of per-item snapshots (with `thumbnail_url`).\n- `buyer` — buyer PII (`vinted_id`, `login`, `name`, `email`, `country_code`); `null` if\n  the order has no linked customer.\n- `account` — the owning Vinted account, including `has_company`.\n\nNote: base `shipping` is the decimal shipping cost (always present). Unknown `include`\ntokens are ignored.\n","properties":{"vat_rate":{"example":"0.20","nullable":true,"type":"string"},"tracking_url":{"nullable":true,"type":"string"},"shipping":{"example":"3.00","nullable":true,"type":"string"},"gross_profit":{"nullable":true,"type":"string"},"order_date":{"format":"date-time","nullable":true,"type":"string"},"account":{"properties":{"country_code":{"nullable":true,"type":"string"},"has_company":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"login":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"items":{"items":{"properties":{"catalog_id":{"nullable":true,"type":"integer"},"id":{"description":"Order item id (use it to PATCH).","format":"uuid","type":"string"},"location":{"nullable":true,"type":"string"},"original_price":{"example":"29.90","nullable":true,"type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"selling_price":{"example":"25.00","nullable":true,"type":"string"},"sku":{"nullable":true,"type":"string"},"supplier_link":{"nullable":true,"type":"string"},"thumbnail_url":{"nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"},"vinted_item_id":{"format":"uuid","nullable":true,"type":"string"}},"type":"object"},"type":"array"},"buyer":{"nullable":true,"properties":{"country_code":{"nullable":true,"type":"string"},"email":{"nullable":true,"type":"string"},"login":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"subtotal_vat":{"example":"2.00","nullable":true,"type":"string"},"status":{"nullable":true,"type":"string"},"vinted_conversation_id":{"description":"Vinted conversation (message thread) id tied to this order. Null when the order has no captured conversation.","nullable":true,"type":"integer"},"note":{"description":"Your private note on the order (never sent to Vinted), max 500 characters. Null when unset. Set it with `PATCH /orders/{id}/note`.","maxLength":500,"nullable":true,"type":"string"},"shipping_deadline_date":{"format":"date-time","nullable":true,"type":"string"},"ready_for_pickup_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"subtotal":{"example":"12.00","nullable":true,"type":"string"},"vinted_transaction_id":{"nullable":true,"type":"integer"},"carrier_name":{"nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"shipping_vat":{"example":"0.00","nullable":true,"type":"string"},"status_updated_at":{"format":"date-time","nullable":true,"type":"string"},"invoice_id":{"format":"uuid","nullable":true,"type":"string"},"item_count":{"type":"integer"},"transaction_user_status":{"enum":["failed","needs_action","completed","waiting"],"nullable":true,"type":"string"},"payout":{"example":"12.00","nullable":true,"type":"string"},"tracking_code":{"nullable":true,"type":"string"},"total_cost":{"nullable":true,"type":"string"},"normalized_status":{"enum":["payment_received","label_ordering","label_failed","label_sent","packed","shipped","ready_for_pickup","delivered","completed","returning","suspended","cancelled"],"nullable":true,"type":"string"},"shipping_label_url":{"description":"Always present. Null until the shipping label has been fetched.","nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"shipping_address":{"description":"Buyer shipping address. Always present (base field).","properties":{"city":{"nullable":true,"type":"string"},"country_code":{"nullable":true,"type":"string"},"line1":{"nullable":true,"type":"string"},"line2":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"postal_code":{"nullable":true,"type":"string"}},"type":"object"},"service_fee":{"example":"0.00","nullable":true,"type":"string"},"original_price":{"nullable":true,"type":"string"}},"type":"object"},"type":"array"},"has_more":{"type":"boolean"},"next_cursor":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Paginated list of orders"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"}},"summary":"List orders","tags":["Orders"]}},"/api/public/v1/orders/{id}":{"get":{"callbacks":{},"description":"Returns a single order by id. Returns 404 if the order belongs to another user.","operationId":"DotbWeb.Api.Public.V1.OrdersController.show","parameters":[{"description":"Order UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Comma-separated list of optional blocks to expand: `items`, `buyer`, `account`. Unknown tokens are ignored. Absent by default (lean response). Note: `shipping_address` and `shipping_label_url` are always-present base fields (not include-gated).","in":"query","name":"include","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"A Vinted order/transaction. Base fields are always present. This includes\n`shipping_label_url` (nullable — null until the label is fetched) and the buyer\n`shipping_address` block; both are always present, not gated behind any include.\n\nOptional blocks are present only when requested via `?include=` (comma-separated):\n\n- `items` — array of per-item snapshots (with `thumbnail_url`).\n- `buyer` — buyer PII (`vinted_id`, `login`, `name`, `email`, `country_code`); `null` if\n  the order has no linked customer.\n- `account` — the owning Vinted account, including `has_company`.\n\nNote: base `shipping` is the decimal shipping cost (always present). Unknown `include`\ntokens are ignored.\n","properties":{"vat_rate":{"example":"0.20","nullable":true,"type":"string"},"tracking_url":{"nullable":true,"type":"string"},"shipping":{"example":"3.00","nullable":true,"type":"string"},"gross_profit":{"nullable":true,"type":"string"},"order_date":{"format":"date-time","nullable":true,"type":"string"},"account":{"properties":{"country_code":{"nullable":true,"type":"string"},"has_company":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"login":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"items":{"items":{"properties":{"catalog_id":{"nullable":true,"type":"integer"},"id":{"description":"Order item id (use it to PATCH).","format":"uuid","type":"string"},"location":{"nullable":true,"type":"string"},"original_price":{"example":"29.90","nullable":true,"type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"selling_price":{"example":"25.00","nullable":true,"type":"string"},"sku":{"nullable":true,"type":"string"},"supplier_link":{"nullable":true,"type":"string"},"thumbnail_url":{"nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"},"vinted_item_id":{"format":"uuid","nullable":true,"type":"string"}},"type":"object"},"type":"array"},"buyer":{"nullable":true,"properties":{"country_code":{"nullable":true,"type":"string"},"email":{"nullable":true,"type":"string"},"login":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"subtotal_vat":{"example":"2.00","nullable":true,"type":"string"},"status":{"nullable":true,"type":"string"},"vinted_conversation_id":{"description":"Vinted conversation (message thread) id tied to this order. Null when the order has no captured conversation.","nullable":true,"type":"integer"},"note":{"description":"Your private note on the order (never sent to Vinted), max 500 characters. Null when unset. Set it with `PATCH /orders/{id}/note`.","maxLength":500,"nullable":true,"type":"string"},"shipping_deadline_date":{"format":"date-time","nullable":true,"type":"string"},"ready_for_pickup_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"subtotal":{"example":"12.00","nullable":true,"type":"string"},"vinted_transaction_id":{"nullable":true,"type":"integer"},"carrier_name":{"nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"shipping_vat":{"example":"0.00","nullable":true,"type":"string"},"status_updated_at":{"format":"date-time","nullable":true,"type":"string"},"invoice_id":{"format":"uuid","nullable":true,"type":"string"},"item_count":{"type":"integer"},"transaction_user_status":{"enum":["failed","needs_action","completed","waiting"],"nullable":true,"type":"string"},"payout":{"example":"12.00","nullable":true,"type":"string"},"tracking_code":{"nullable":true,"type":"string"},"total_cost":{"nullable":true,"type":"string"},"normalized_status":{"enum":["payment_received","label_ordering","label_failed","label_sent","packed","shipped","ready_for_pickup","delivered","completed","returning","suspended","cancelled"],"nullable":true,"type":"string"},"shipping_label_url":{"description":"Always present. Null until the shipping label has been fetched.","nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"shipping_address":{"description":"Buyer shipping address. Always present (base field).","properties":{"city":{"nullable":true,"type":"string"},"country_code":{"nullable":true,"type":"string"},"line1":{"nullable":true,"type":"string"},"line2":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"postal_code":{"nullable":true,"type":"string"}},"type":"object"},"service_fee":{"example":"0.00","nullable":true,"type":"string"},"original_price":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Order"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Not found"}},"summary":"Get order","tags":["Orders"]}},"/api/public/v1/orders/{id}/pack":{"post":{"callbacks":{},"description":"Marks an order as packed (a Dotb fulfillment status between label_sent and shipped). Only orders currently in `label_sent` can be packed; any other status returns 409. This is a local status change only — nothing is pushed to Vinted.","operationId":"DotbWeb.Api.Public.V1.OrdersController.pack","parameters":[{"description":"Order UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"A Vinted order/transaction. Base fields are always present. This includes\n`shipping_label_url` (nullable — null until the label is fetched) and the buyer\n`shipping_address` block; both are always present, not gated behind any include.\n\nOptional blocks are present only when requested via `?include=` (comma-separated):\n\n- `items` — array of per-item snapshots (with `thumbnail_url`).\n- `buyer` — buyer PII (`vinted_id`, `login`, `name`, `email`, `country_code`); `null` if\n  the order has no linked customer.\n- `account` — the owning Vinted account, including `has_company`.\n\nNote: base `shipping` is the decimal shipping cost (always present). Unknown `include`\ntokens are ignored.\n","properties":{"vat_rate":{"example":"0.20","nullable":true,"type":"string"},"tracking_url":{"nullable":true,"type":"string"},"shipping":{"example":"3.00","nullable":true,"type":"string"},"gross_profit":{"nullable":true,"type":"string"},"order_date":{"format":"date-time","nullable":true,"type":"string"},"account":{"properties":{"country_code":{"nullable":true,"type":"string"},"has_company":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"login":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"items":{"items":{"properties":{"catalog_id":{"nullable":true,"type":"integer"},"id":{"description":"Order item id (use it to PATCH).","format":"uuid","type":"string"},"location":{"nullable":true,"type":"string"},"original_price":{"example":"29.90","nullable":true,"type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"selling_price":{"example":"25.00","nullable":true,"type":"string"},"sku":{"nullable":true,"type":"string"},"supplier_link":{"nullable":true,"type":"string"},"thumbnail_url":{"nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"},"vinted_item_id":{"format":"uuid","nullable":true,"type":"string"}},"type":"object"},"type":"array"},"buyer":{"nullable":true,"properties":{"country_code":{"nullable":true,"type":"string"},"email":{"nullable":true,"type":"string"},"login":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"subtotal_vat":{"example":"2.00","nullable":true,"type":"string"},"status":{"nullable":true,"type":"string"},"vinted_conversation_id":{"description":"Vinted conversation (message thread) id tied to this order. Null when the order has no captured conversation.","nullable":true,"type":"integer"},"note":{"description":"Your private note on the order (never sent to Vinted), max 500 characters. Null when unset. Set it with `PATCH /orders/{id}/note`.","maxLength":500,"nullable":true,"type":"string"},"shipping_deadline_date":{"format":"date-time","nullable":true,"type":"string"},"ready_for_pickup_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"subtotal":{"example":"12.00","nullable":true,"type":"string"},"vinted_transaction_id":{"nullable":true,"type":"integer"},"carrier_name":{"nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"shipping_vat":{"example":"0.00","nullable":true,"type":"string"},"status_updated_at":{"format":"date-time","nullable":true,"type":"string"},"invoice_id":{"format":"uuid","nullable":true,"type":"string"},"item_count":{"type":"integer"},"transaction_user_status":{"enum":["failed","needs_action","completed","waiting"],"nullable":true,"type":"string"},"payout":{"example":"12.00","nullable":true,"type":"string"},"tracking_code":{"nullable":true,"type":"string"},"total_cost":{"nullable":true,"type":"string"},"normalized_status":{"enum":["payment_received","label_ordering","label_failed","label_sent","packed","shipped","ready_for_pickup","delivered","completed","returning","suspended","cancelled"],"nullable":true,"type":"string"},"shipping_label_url":{"description":"Always present. Null until the shipping label has been fetched.","nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"shipping_address":{"description":"Buyer shipping address. Always present (base field).","properties":{"city":{"nullable":true,"type":"string"},"country_code":{"nullable":true,"type":"string"},"line1":{"nullable":true,"type":"string"},"line2":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"postal_code":{"nullable":true,"type":"string"}},"type":"object"},"service_fee":{"example":"0.00","nullable":true,"type":"string"},"original_price":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Updated order (normalized_status: packed)"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Order not found"},"409":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Order not in a packable state"}},"summary":"Mark order as packed","tags":["Orders"]}},"/api/public/v1/orders/{id}/shipping-label":{"post":{"callbacks":{},"description":"Orders the Vinted shipping label for an order.\n\nRequires the order's Vinted account to have the extension bridge up and running — otherwise the call returns **504** with `details.reason = \"bridge_offline\"`.\n\nThe call then waits up to ~35s for Vinted to generate the PDF before responding, so it is deliberately slow.\n\nOnly orders in `payment_received` or `label_failed` can order a label; any other status returns 409.\n\n**Not idempotent, and rate limited.** Once the request reaches Vinted the label is ordered, even if this call then times out — so an order that just ordered a label is barred from ordering another for a few minutes, returning **429** with a `Retry-After` header. Do not blindly retry: re-read the order first.","operationId":"DotbWeb.Api.Public.V1.OrdersController.order_shipping_label","parameters":[{"description":"Order UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Optional shipping-label preferences.","properties":{"label_type":{"default":"printable","description":"Preferred label format. Applied only when the carrier actually offers a choice; otherwise Vinted's default for the method the buyer paid for is used. A preference that isn't on offer is not an error — check `label_type` in the response.","enum":["printable","digital"],"type":"string"}},"type":"object"}}},"description":"Shipping-label preferences","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"label_ready":{"description":"Whether Vinted generated the label PDF before this request's wait budget ran out. `false` still means the label WAS ordered — poll `GET /orders/{id}` until `shipping_label_url` is set.","type":"boolean"},"label_type":{"description":"The label type actually sent to Vinted. `null` means Vinted's own default was used (the carrier offered no choice, or the preference wasn't on offer).","enum":["printable","digital"],"nullable":true,"type":"string"},"order":{"description":"A Vinted order/transaction. Base fields are always present. This includes\n`shipping_label_url` (nullable — null until the label is fetched) and the buyer\n`shipping_address` block; both are always present, not gated behind any include.\n\nOptional blocks are present only when requested via `?include=` (comma-separated):\n\n- `items` — array of per-item snapshots (with `thumbnail_url`).\n- `buyer` — buyer PII (`vinted_id`, `login`, `name`, `email`, `country_code`); `null` if\n  the order has no linked customer.\n- `account` — the owning Vinted account, including `has_company`.\n\nNote: base `shipping` is the decimal shipping cost (always present). Unknown `include`\ntokens are ignored.\n","properties":{"vat_rate":{"example":"0.20","nullable":true,"type":"string"},"tracking_url":{"nullable":true,"type":"string"},"shipping":{"example":"3.00","nullable":true,"type":"string"},"gross_profit":{"nullable":true,"type":"string"},"order_date":{"format":"date-time","nullable":true,"type":"string"},"account":{"properties":{"country_code":{"nullable":true,"type":"string"},"has_company":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"login":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"items":{"items":{"properties":{"catalog_id":{"nullable":true,"type":"integer"},"id":{"description":"Order item id (use it to PATCH).","format":"uuid","type":"string"},"location":{"nullable":true,"type":"string"},"original_price":{"example":"29.90","nullable":true,"type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"selling_price":{"example":"25.00","nullable":true,"type":"string"},"sku":{"nullable":true,"type":"string"},"supplier_link":{"nullable":true,"type":"string"},"thumbnail_url":{"nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"},"vinted_item_id":{"format":"uuid","nullable":true,"type":"string"}},"type":"object"},"type":"array"},"buyer":{"nullable":true,"properties":{"country_code":{"nullable":true,"type":"string"},"email":{"nullable":true,"type":"string"},"login":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"subtotal_vat":{"example":"2.00","nullable":true,"type":"string"},"status":{"nullable":true,"type":"string"},"vinted_conversation_id":{"description":"Vinted conversation (message thread) id tied to this order. Null when the order has no captured conversation.","nullable":true,"type":"integer"},"note":{"description":"Your private note on the order (never sent to Vinted), max 500 characters. Null when unset. Set it with `PATCH /orders/{id}/note`.","maxLength":500,"nullable":true,"type":"string"},"shipping_deadline_date":{"format":"date-time","nullable":true,"type":"string"},"ready_for_pickup_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"subtotal":{"example":"12.00","nullable":true,"type":"string"},"vinted_transaction_id":{"nullable":true,"type":"integer"},"carrier_name":{"nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"shipping_vat":{"example":"0.00","nullable":true,"type":"string"},"status_updated_at":{"format":"date-time","nullable":true,"type":"string"},"invoice_id":{"format":"uuid","nullable":true,"type":"string"},"item_count":{"type":"integer"},"transaction_user_status":{"enum":["failed","needs_action","completed","waiting"],"nullable":true,"type":"string"},"payout":{"example":"12.00","nullable":true,"type":"string"},"tracking_code":{"nullable":true,"type":"string"},"total_cost":{"nullable":true,"type":"string"},"normalized_status":{"enum":["payment_received","label_ordering","label_failed","label_sent","packed","shipped","ready_for_pickup","delivered","completed","returning","suspended","cancelled"],"nullable":true,"type":"string"},"shipping_label_url":{"description":"Always present. Null until the shipping label has been fetched.","nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"shipping_address":{"description":"Buyer shipping address. Always present (base field).","properties":{"city":{"nullable":true,"type":"string"},"country_code":{"nullable":true,"type":"string"},"line1":{"nullable":true,"type":"string"},"line2":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"postal_code":{"nullable":true,"type":"string"}},"type":"object"},"service_fee":{"example":"0.00","nullable":true,"type":"string"},"original_price":{"nullable":true,"type":"string"}},"type":"object"}},"type":"object"}}},"description":"Label ordered"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Order not found"},"409":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Order cannot order a label in its current status"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Invalid label_type"},"429":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"A label was already ordered for this order minutes ago"},"503":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Bridge busy, captcha, or Vinted refused"},"504":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"The extension bridge is not up and running for this Vinted account"}},"summary":"Order the shipping label","tags":["Orders"]}},"/api/public/v1/orders/{id}/note":{"patch":{"callbacks":{},"description":"Sets or clears your private note on an order — the same note shown in the dashboard. It is stored in Dotb only and never sent to Vinted.\n\nThe `note` key is required: send `null` or `\"\"` to clear the note. A note longer than 500 characters, a missing `note` key or a non-string value returns **422** with the reason under `details.note`; the stored note is left unchanged.","operationId":"DotbWeb.Api.Public.V1.OrdersController.update_note","parameters":[{"description":"Order UUID.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"note":{"description":"The new note, max 500 characters. Replaces the current note entirely. `null` or `\"\"` clears it.","example":"Ship in the blue box","maxLength":500,"nullable":true,"type":"string"}},"required":["note"],"type":"object"}}},"description":"The new note","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"description":"A Vinted order/transaction. Base fields are always present. This includes\n`shipping_label_url` (nullable — null until the label is fetched) and the buyer\n`shipping_address` block; both are always present, not gated behind any include.\n\nOptional blocks are present only when requested via `?include=` (comma-separated):\n\n- `items` — array of per-item snapshots (with `thumbnail_url`).\n- `buyer` — buyer PII (`vinted_id`, `login`, `name`, `email`, `country_code`); `null` if\n  the order has no linked customer.\n- `account` — the owning Vinted account, including `has_company`.\n\nNote: base `shipping` is the decimal shipping cost (always present). Unknown `include`\ntokens are ignored.\n","properties":{"vat_rate":{"example":"0.20","nullable":true,"type":"string"},"tracking_url":{"nullable":true,"type":"string"},"shipping":{"example":"3.00","nullable":true,"type":"string"},"gross_profit":{"nullable":true,"type":"string"},"order_date":{"format":"date-time","nullable":true,"type":"string"},"account":{"properties":{"country_code":{"nullable":true,"type":"string"},"has_company":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"login":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"items":{"items":{"properties":{"catalog_id":{"nullable":true,"type":"integer"},"id":{"description":"Order item id (use it to PATCH).","format":"uuid","type":"string"},"location":{"nullable":true,"type":"string"},"original_price":{"example":"29.90","nullable":true,"type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"selling_price":{"example":"25.00","nullable":true,"type":"string"},"sku":{"nullable":true,"type":"string"},"supplier_link":{"nullable":true,"type":"string"},"thumbnail_url":{"nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"},"vinted_item_id":{"format":"uuid","nullable":true,"type":"string"}},"type":"object"},"type":"array"},"buyer":{"nullable":true,"properties":{"country_code":{"nullable":true,"type":"string"},"email":{"nullable":true,"type":"string"},"login":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"}},"type":"object"},"subtotal_vat":{"example":"2.00","nullable":true,"type":"string"},"status":{"nullable":true,"type":"string"},"vinted_conversation_id":{"description":"Vinted conversation (message thread) id tied to this order. Null when the order has no captured conversation.","nullable":true,"type":"integer"},"note":{"description":"Your private note on the order (never sent to Vinted), max 500 characters. Null when unset. Set it with `PATCH /orders/{id}/note`.","maxLength":500,"nullable":true,"type":"string"},"shipping_deadline_date":{"format":"date-time","nullable":true,"type":"string"},"ready_for_pickup_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"subtotal":{"example":"12.00","nullable":true,"type":"string"},"vinted_transaction_id":{"nullable":true,"type":"integer"},"carrier_name":{"nullable":true,"type":"string"},"currency":{"example":"EUR","nullable":true,"type":"string"},"shipping_vat":{"example":"0.00","nullable":true,"type":"string"},"status_updated_at":{"format":"date-time","nullable":true,"type":"string"},"invoice_id":{"format":"uuid","nullable":true,"type":"string"},"item_count":{"type":"integer"},"transaction_user_status":{"enum":["failed","needs_action","completed","waiting"],"nullable":true,"type":"string"},"payout":{"example":"12.00","nullable":true,"type":"string"},"tracking_code":{"nullable":true,"type":"string"},"total_cost":{"nullable":true,"type":"string"},"normalized_status":{"enum":["payment_received","label_ordering","label_failed","label_sent","packed","shipped","ready_for_pickup","delivered","completed","returning","suspended","cancelled"],"nullable":true,"type":"string"},"shipping_label_url":{"description":"Always present. Null until the shipping label has been fetched.","nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"shipping_address":{"description":"Buyer shipping address. Always present (base field).","properties":{"city":{"nullable":true,"type":"string"},"country_code":{"nullable":true,"type":"string"},"line1":{"nullable":true,"type":"string"},"line2":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"postal_code":{"nullable":true,"type":"string"}},"type":"object"},"service_fee":{"example":"0.00","nullable":true,"type":"string"},"original_price":{"nullable":true,"type":"string"}},"type":"object"}}},"description":"Updated order"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Order not found"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Note missing, not a string, or longer than 500 characters"}},"summary":"Set the order note","tags":["Orders"]}},"/api/public/v1/orders/{order_id}/items/{id}":{"patch":{"callbacks":{},"description":"Updates the inventory fields (`sku`, `location`, `supplier_link`, `purchase_price`) of an item within an order — the same fields editable in the dashboard. Only the fields you send are changed; setting `purchase_price` recalculates the order's profit totals. Returns 404 if the order or item is not found or belongs to another user.","operationId":"DotbWeb.Api.Public.V1.OrdersController.update_item","parameters":[{"description":"Order UUID.","in":"path","name":"order_id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Order item UUID (the `id` field of an order's `items` entry).","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Order-item inventory fields to update. All optional — only the fields you send are changed. Setting `purchase_price` recalculates the order's profit totals.","properties":{"location":{"description":"Storage location.","nullable":true,"type":"string"},"purchase_price":{"description":"Your cost price (decimal string).","example":"15.00","nullable":true,"type":"string"},"sku":{"description":"Seller SKU for inventory.","nullable":true,"type":"string"},"supplier_link":{"description":"Source URL; `https://` is prepended when no scheme is given.","nullable":true,"type":"string"}},"type":"object"}}},"description":"Order item fields to update","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"catalog_id":{"nullable":true,"type":"integer"},"id":{"description":"Order item id (use it to PATCH).","format":"uuid","type":"string"},"location":{"nullable":true,"type":"string"},"original_price":{"example":"29.90","nullable":true,"type":"string"},"purchase_price":{"example":"15.00","nullable":true,"type":"string"},"selling_price":{"example":"25.00","nullable":true,"type":"string"},"sku":{"nullable":true,"type":"string"},"supplier_link":{"nullable":true,"type":"string"},"thumbnail_url":{"nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"vinted_id":{"nullable":true,"type":"integer"},"vinted_item_id":{"format":"uuid","nullable":true,"type":"string"}},"type":"object"}}},"description":"Updated order item"},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Subscription required"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Order or item not found"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"details":{"type":"object"},"message":{"example":"Resource not found","type":"string"},"request_id":{"nullable":true,"type":"string"},"type":{"example":"not_found","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Validation error"}},"summary":"Update an order item","tags":["Orders"]}}},"security":[{"bearer":[]}],"servers":[{"url":"https://dotb.io","variables":{}}],"tags":[{"name":"Accounts"},{"name":"Catalogs"},{"name":"Brands"},{"name":"Colors"},{"name":"Video game ratings"},{"name":"Items"},{"name":"Scheduled publishes"},{"name":"Orders"}]}