{
  "openapi": "3.1.0",
  "info": {
    "title": "ScrapeBadger Vinted API",
    "version": "1.0.0",
    "description": "Vinted marketplace scraping API for searching items, fetching details, user profiles, and reference data."
  },
  "servers": [
    {
      "url": "https://scrapebadger.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKeyAuth": []
    }
  ],
  "paths": {
    "/v1/vinted/search": {
      "get": {
        "operationId": "searchVintedItems",
        "summary": "Search Items",
        "description": "Search Vinted catalog items with filters.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "description": "Search query string. Matches against item titles and descriptions."
          },
          {
            "name": "market",
            "in": "query",
            "schema": { "type": "string", "default": "fr" },
            "description": "Vinted market to search (e.g. fr, de, uk, it, es, pl, us)."
          },
          {
            "name": "page",
            "in": "query",
            "schema": { "type": "integer", "default": 1, "minimum": 1 },
            "description": "Page number for paginated results."
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 96 },
            "description": "Number of items per page."
          },
          {
            "name": "price_from",
            "in": "query",
            "schema": { "type": "number" },
            "description": "Minimum price filter in the market's local currency."
          },
          {
            "name": "price_to",
            "in": "query",
            "schema": { "type": "number" },
            "description": "Maximum price filter in the market's local currency."
          },
          {
            "name": "catalog_ids",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Comma-separated Vinted catalog (category) IDs to restrict the search to (e.g. \"221\" or \"221,1242\"). Applied by Vinted before the search runs, and sub-categories are included. A catalog ID is the `catalog[]` value in a Vinted category URL (vinted.fr/catalog?catalog[]=221); IDs are per market."
          },
          {
            "name": "brand_ids",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Comma-separated list of brand IDs to filter by."
          },
          {
            "name": "color_ids",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Comma-separated list of color IDs to filter by."
          },
          {
            "name": "status_ids",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Comma-separated list of condition status IDs to filter by."
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "relevance",
              "enum": ["relevance", "price_low_to_high", "price_high_to_low", "newest_first"]
            },
            "description": "Sort order for results."
          },
          {
            "name": "seller_country",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Comma-separated ISO 3166-1 alpha-2 country codes (case-insensitive) to keep only items whose seller is physically located in one of those countries (e.g. \"fr\" or \"fr,be\"). Vinted markets federate cross-border listings; this filters on the seller's real location, which is a different axis from `market`. Note: pagination totals stay unfiltered, so a page may return fewer than `per_page` items after filtering. Billing: a search is a flat 5 credits whatever filters you pass; seller lookups are not billed on top."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful search",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/VintedItemSummary" }
                    },
                    "pagination": { "$ref": "#/components/schemas/VintedPagination" },
                    "market": { "type": "string", "description": "Echo of the market that was searched." },
                    "seller_country": { "type": "string", "nullable": true, "description": "Echo of the normalized seller_country filter that was applied (uppercase, comma-separated ISO-2 codes, e.g. \"FR,BE\"), or null when no filter was requested." }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/vinted/items/{item_id}": {
      "get": {
        "operationId": "getVintedItemDetail",
        "summary": "Get Item Details",
        "description": "Get detailed information about a Vinted item.",
        "parameters": [
          {
            "name": "item_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The unique Vinted item ID."
          },
          {
            "name": "market",
            "in": "query",
            "schema": { "type": "string", "default": "fr" },
            "description": "Vinted market where the item is listed (e.g. fr, de, uk)."
          }
        ],
        "responses": {
          "200": {
            "description": "Item details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "item": { "$ref": "#/components/schemas/VintedItemDetail" },
                    "market": { "type": "string", "description": "Echo of the requested market." }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/vinted/users/{user_id}": {
      "get": {
        "operationId": "getVintedUserProfile",
        "summary": "Get User Profile",
        "description": "Get detailed profile information for a Vinted user.",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The unique Vinted user ID."
          },
          {
            "name": "market",
            "in": "query",
            "schema": { "type": "string", "default": "fr" },
            "description": "Vinted market where the user is registered (e.g. fr, de, uk)."
          }
        ],
        "responses": {
          "200": {
            "description": "User profile",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "integer", "description": "User ID." },
                    "login": { "type": "string", "description": "Username." },
                    "photo": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "url": { "type": "string" },
                        "width": { "type": "integer" },
                        "height": { "type": "integer" }
                      },
                      "description": "Profile photo."
                    },
                    "given_item_count": { "type": "integer", "description": "Number of items the user has sold." },
                    "item_count": { "type": "integer", "description": "Number of items currently listed." },
                    "followers_count": { "type": "integer", "description": "Number of followers." },
                    "following_count": { "type": "integer", "description": "Number of users followed." },
                    "feedback_reputation": { "type": "number", "description": "Reputation score between 0 and 1." },
                    "feedback_count": { "type": "integer", "description": "Total number of feedback ratings received." },
                    "city": { "type": "string", "nullable": true, "description": "User's city (if public)." },
                    "country_title": { "type": "string", "nullable": true, "description": "User's country." },
                    "last_loged_on": { "type": "string", "nullable": true, "description": "ISO 8601 timestamp of last login." },
                    "created_at": { "type": "string", "nullable": true, "description": "ISO 8601 timestamp when the account was created." }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/vinted/users/{user_id}/items": {
      "get": {
        "operationId": "getVintedUserItems",
        "summary": "Get User Items",
        "description": "List all active items from a specific Vinted user.",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The unique Vinted user ID."
          },
          {
            "name": "market",
            "in": "query",
            "schema": { "type": "string", "default": "fr" },
            "description": "Vinted market where the user is registered (e.g. fr, de, uk)."
          },
          {
            "name": "page",
            "in": "query",
            "schema": { "type": "integer", "default": 1, "minimum": 1 },
            "description": "Page number for paginated results."
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": { "type": "integer", "default": 24, "minimum": 1, "maximum": 96 },
            "description": "Number of items per page."
          }
        ],
        "responses": {
          "200": {
            "description": "User items list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/VintedItemSummary" }
                    },
                    "total_entries": { "type": "integer", "description": "Total number of items listed by this user." },
                    "current_page": { "type": "integer", "description": "Current page number." },
                    "per_page": { "type": "integer", "description": "Number of items per page." }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/vinted/brands": {
      "get": {
        "operationId": "searchVintedBrands",
        "summary": "Search Brands",
        "description": "Search for Vinted brand IDs by name.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "description": "Brand name to search for. Partial matches are supported."
          },
          {
            "name": "market",
            "in": "query",
            "schema": { "type": "string", "default": "fr" },
            "description": "Vinted market to search brands in."
          }
        ],
        "responses": {
          "200": {
            "description": "Brand search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "brands": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": { "type": "integer", "description": "Brand ID." },
                          "title": { "type": "string", "description": "Brand name." },
                          "slug": { "type": "string", "description": "URL-friendly brand name." },
                          "favourite_count": { "type": "integer", "description": "Number of users following this brand." },
                          "item_count": { "type": "integer", "description": "Number of items listed under this brand." }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/vinted/colors": {
      "get": {
        "operationId": "listVintedColors",
        "summary": "List Colors",
        "description": "List all available color filters for Vinted search.",
        "parameters": [
          {
            "name": "market",
            "in": "query",
            "schema": { "type": "string", "default": "fr" },
            "description": "Vinted market. Color names are localized to the market language."
          }
        ],
        "responses": {
          "200": {
            "description": "Available colors",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "colors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": { "type": "integer", "description": "Color ID." },
                          "title": { "type": "string", "description": "Localized color name." },
                          "hex": { "type": "string", "description": "Hex color code (e.g. \"#000000\")." }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/vinted/statuses": {
      "get": {
        "operationId": "listVintedStatuses",
        "summary": "List Conditions",
        "description": "List all available item condition statuses for Vinted search.",
        "parameters": [
          {
            "name": "market",
            "in": "query",
            "schema": { "type": "string", "default": "fr" },
            "description": "Vinted market. Status names are localized to the market language."
          }
        ],
        "responses": {
          "200": {
            "description": "Available item conditions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statuses": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": { "type": "integer", "description": "Status ID." },
                          "title": { "type": "string", "description": "Localized condition label." }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/vinted/markets": {
      "get": {
        "operationId": "listVintedMarkets",
        "summary": "List Markets",
        "description": "List all supported Vinted markets with their domains and country codes.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Supported markets",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "markets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": { "type": "string", "description": "Market code (e.g. \"fr\", \"de\")." },
                          "title": { "type": "string", "description": "Country name." },
                          "domain": { "type": "string", "description": "Vinted domain for this market." },
                          "currency": { "type": "string", "description": "ISO 4217 currency code." }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "schemas": {
      "VintedItemSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "Item ID." },
          "title": { "type": "string", "description": "Item title." },
          "price": { "$ref": "#/components/schemas/VintedPrice" },
          "service_fee": { "type": "string", "nullable": true, "description": "Buyer-protection fee as a decimal string, in price.currency_code." },
          "total_item_price": { "type": "string", "nullable": true, "description": "Price + buyer protection as a decimal string, in price.currency_code." },
          "brand_title": { "type": "string", "nullable": true, "description": "Brand name." },
          "size_title": { "type": "string", "nullable": true, "description": "Size label." },
          "status": { "type": "string", "nullable": true, "description": "Item condition, localized to the market." },
          "photo": { "$ref": "#/components/schemas/VintedPhoto" },
          "photos": { "type": "array", "items": { "$ref": "#/components/schemas/VintedPhoto" } },
          "url": { "type": "string", "description": "Full URL to the Vinted listing." },
          "path": { "type": "string", "nullable": true, "description": "Path portion of the listing URL." },
          "user": { "$ref": "#/components/schemas/VintedUserSummary" },
          "favourite_count": { "type": "integer", "description": "Number of users who favourited this item." },
          "view_count": { "type": "integer", "description": "Number of views." },
          "is_visible": { "type": "boolean", "description": "Whether the listing is publicly visible." },
          "promoted": { "type": "boolean", "description": "Whether the listing is a promoted/bumped placement." },
          "content_source": { "type": "string", "nullable": true, "description": "Vinted's own label for where the result came from (e.g. \"search\")." },
          "seller_country_code": { "type": "string", "nullable": true, "description": "ISO 3166-1 alpha-2 code of the seller's physical country (e.g. \"IT\"). Populated only when seller_country filtering was requested." }
        }
      },
      "VintedPhoto": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "Photo ID." },
          "url": { "type": "string", "description": "Photo URL." },
          "full_size_url": { "type": "string", "nullable": true, "description": "Full-resolution photo URL." },
          "width": { "type": "integer", "nullable": true, "description": "Width in pixels." },
          "height": { "type": "integer", "nullable": true, "description": "Height in pixels." },
          "dominant_color": { "type": "string", "nullable": true, "description": "Dominant colour as a hex string." },
          "is_main": { "type": "boolean", "description": "Whether this is the listing's primary photo." }
        }
      },
      "VintedUserSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "User ID." },
          "login": { "type": "string", "description": "Username." },
          "photo_url": { "type": "string", "nullable": true, "description": "Profile photo URL." },
          "business": { "type": "boolean", "description": "Whether the seller is a business account." }
        }
      },
      "VintedSellerSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "Seller ID." },
          "login": { "type": "string", "description": "Username." },
          "photo_url": { "type": "string", "nullable": true, "description": "Profile photo URL." },
          "business": { "type": "boolean", "description": "Whether the seller is a business account." },
          "feedback_count": { "type": "integer", "description": "Number of reviews received." },
          "feedback_reputation": { "type": "number", "description": "Reputation score between 0 and 1." },
          "item_count": { "type": "integer", "description": "Number of items listed." },
          "location": { "type": "string", "nullable": true, "description": "Seller location as shown on the listing." },
          "last_seen": { "type": "string", "nullable": true, "description": "Vinted's relative last-seen label, localized." },
          "badges": { "type": "array", "items": { "type": "string" }, "description": "Seller badges (e.g. ACTIVE_LISTER)." }
        }
      },
      "VintedPrice": {
        "type": "object",
        "properties": {
          "amount": { "type": "string", "description": "Decimal amount as a string (e.g. \"45.0\")." },
          "currency_code": { "type": "string", "description": "ISO 4217 currency code (e.g. \"EUR\")." }
        }
      },
      "VintedPagination": {
        "type": "object",
        "properties": {
          "current_page": { "type": "integer", "description": "Current page number." },
          "per_page": { "type": "integer", "description": "Number of items per page." },
          "total_pages": { "type": "integer", "description": "Total number of pages." },
          "total_entries": { "type": "integer", "description": "Total matching items. Vinted caps this at 960 on deep result sets — treat it as an upper bound." }
        }
      },
      "VintedItemDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/VintedItemSummary" },
          {
            "type": "object",
            "properties": {
              "description": { "type": "string", "nullable": true, "description": "Full item description text." },
              "catalog_id": { "type": "integer", "nullable": true, "description": "Vinted catalog (category) ID — the value to pass as catalog_ids on search." },
              "brand_id": { "type": "integer", "nullable": true, "description": "Vinted brand ID — the value to pass as brand_ids on search." },
              "category": { "type": "array", "items": { "type": "string" }, "description": "Category breadcrumb, root first. Localized to the market." },
              "size_id": { "type": "integer", "nullable": true, "description": "Vinted size ID." },
              "status_id": { "type": "integer", "nullable": true, "description": "Vinted condition ID." },
              "color1": { "type": "string", "nullable": true, "description": "Primary color, localized." },
              "color2": { "type": "string", "nullable": true, "description": "Secondary color." },
              "upload_date": { "type": "string", "nullable": true, "description": "Vinted's relative \"listed\" label, localized (e.g. \"Il y a une semaine\") — not an ISO timestamp." },
              "can_buy": { "type": "boolean" },
              "instant_buy": { "type": "boolean" },
              "can_bundle": { "type": "boolean" },
              "can_reserve": { "type": "boolean" },
              "is_favourite": { "type": "boolean" },
              "is_reserved": { "type": "boolean" },
              "is_closed": { "type": "boolean" },
              "is_hidden": { "type": "boolean" },
              "seller": { "$ref": "#/components/schemas/VintedSellerSummary" }
            }
          }
        ]
      }
    }
  }
}
