{
  "openapi": "3.1.0",
  "info": {
    "title": "Trawl API",
    "version": "2026-10-01",
    "summary": "eBay sold-listings data over HTTPS. Send a request with an API key, get JSON back.",
    "termsOfService": "https://trawl.dev/terms",
    "contact": {
      "name": "Trawl",
      "url": "https://trawl.dev/docs"
    },
    "description": "Trawl serves data about completed eBay sales on the ebay.com (`EBAY_US`) and\nebay.co.uk (`EBAY_GB`) marketplaces: the final price, sale date, condition and\nshipping of each sold listing, and the listing's page-level details (item\nspecifics, description, images, seller, returns).\n\nTrawl is an independent service and is not affiliated with or endorsed by\neBay Inc. This is not eBay's own API.\n\n## Base URL\n\nEvery path has the form `https://api.trawl.dev/{product}/{version}/{endpoint}`.\nThe eBay endpoints live under `https://api.trawl.dev/ebay/v1`. The one\nexception is `GET https://api.trawl.dev/health`, which reports on every\nproduct at once and is free. All requests use HTTPS and all responses are\nJSON.\n\n## Authentication\n\nSend your API key in the `x-api-key` request header on every request. Keys\nstart with `sk_` and are account-wide: one key works on every endpoint. Keys\nare created and deleted at https://trawl.dev/console/keys. Do not put the key\nin a query string, and call the API from server-side code only.\n\n## Credits\n\nUsage is measured in credits. A plan includes a monthly credit allowance\nshared by all of the account's API keys.\n\n- A successful call costs 1 credit, with two exceptions on the sold-listings\n  search: it costs 1 credit per page of 100 results returned, and 2 credits\n  per page when `details` is set.\n- A successful response that returns nothing is free: a search with no\n  matches, a category lookup with no matches and a lookup of a listing eBay\n  has removed all answer `200` with `credits_charged` set to `0`.\n- Only `2xx` responses are charged. Every error is free.\n- Each successful response states its cost in the `credits_charged` body\n  field and in the `X-Credits-Charged` response header.\n- Before a request runs, its maximum possible cost is checked against the\n  credits the account has left, less the maximum cost of the account's\n  requests that are still running. A request the account could not pay for\n  in the worst case is refused with `429` and is not charged.\n- The allowance window follows the account's billing cycle and resets when\n  the subscription starts or renews. A plan change keeps the current window:\n  an upgrade raises the allowance at once (the credits used so far stay used),\n  a downgrade takes effect at the renewal. Free accounts reset on the first\n  day of each calendar month (UTC).\n\n## Rate limits\n\nEach plan also has a per-second request rate, counted per account over a\nsliding one-second window. A request over the rate is refused with `429` and a\n`Retry-After: 1` header. Requests refused with `429` do not count toward the\nrate, and neither does a request that fails with `503` because the service\ncould not be reached. Every other request counts, including one that is\nrejected with `400` or `404`. Plan allowances and rates are listed at\nhttps://trawl.dev/pricing.\n\nOnce the API key has been verified, every response carries the account's\nstanding in these headers: `X-RateLimit-Limit` (credits in the plan per\nbilling window), `X-RateLimit-Remaining` (credits left), `X-RateLimit-Reset`\n(Unix timestamp, in seconds, of the end of the window) and `X-Credits-Charged`\n(credits this response cost). Responses produced before the key is verified\n(`403`, `404` for an unknown path, `413`) do not carry them.\n\n## Errors\n\nEvery non-`2xx` response is a JSON object with a single `error` string that\nnames the parameter and the rule it broke, or the reason the request was\nrefused.\n\n| Status | Meaning |\n| --- | --- |\n| `400` | A parameter failed validation. |\n| `403` | The API key is missing, invalid or revoked. |\n| `404` | Unknown path, or `/item` details that are not available yet. |\n| `413` | The request body is larger than 262,144 bytes. |\n| `429` | With `Retry-After`: the per-second rate was exceeded. Without: the monthly credits are spent, or too few remain to cover the request. |\n| `500` | Internal error. |\n| `503` | The service is temporarily unavailable. Safe to retry with backoff. |\n"
  },
  "servers": [
    {
      "url": "https://api.trawl.dev",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "eBay",
      "description": "Sold listings, listing details and category lookup for the ebay.com and ebay.co.uk marketplaces."
    },
    {
      "name": "Status",
      "description": "Whether the API is up and how current its data is. Free."
    }
  ],
  "paths": {
    "/ebay/v1/sold": {
      "get": {
        "operationId": "sold",
        "tags": [
          "eBay"
        ],
        "summary": "Search sold listings",
        "description": "Returns sold listings whose title contains every word of `query`, in any\norder — or, with `category` and no `query`, every sale in that category.\nResults are always ordered newest sale first; there is no sort parameter.\n\nMatching is on whole words, case- and accent-insensitive. Words are split on\nevery non-alphanumeric character, so `64GB`, `s21` and `44mm` are each one\nword, and `iphone` does not match `iphones`.\n\n**Paging.** A page is 100 results. `max_pages` sets how many pages are\nreturned, and all of them arrive in this one response: up to\n`max_pages` × 100 results, 2,000 at most. When `count` equals\n`max_pages` × 100 the response is full and more may exist: it then\ncarries `next_cursor`, a string to send back unchanged as `cursor` on the\nsame search for the next pages, from exactly where this response stopped.\nRepeat until `next_cursor` is `null`. A cursor walks as far as the data\ngoes, is never stored or expired server-side, and is bound to the search\nthat issued it (the same `site`, `query`, `exclude`, `category`, prices,\ndates, `condition`, `attr` and `details`; only `max_pages` may change) —\non any other search it answers `400`.\n\n**A whole category.** `query` is required only when there is no\n`category`: a leaf category on its own returns every sale in it, newest\nfirst, and the cursor walks the rest.\n\n**Cost.** 1 credit per page of results returned (`count` ÷ 100, rounded\nup), or 2 credits per page when `details` is set. A search that matches\nnothing answers `200` with `count` 0 and costs nothing. `max_pages` is the\nmost the request can cost, not its price. The request is refused with\n`429` when the account's remaining credits do not cover `max_pages`\n(doubled with `details`).\n\n**Listing details.** With `details` set, each result carries a `details`\nobject identical to what `GET /ebay/v1/item` returns for its `item_id`,\nand results are limited to listings whose details are available and\nlistings eBay has removed.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/Query"
          },
          {
            "$ref": "#/components/parameters/Site"
          },
          {
            "$ref": "#/components/parameters/Exclude"
          },
          {
            "$ref": "#/components/parameters/Category"
          },
          {
            "$ref": "#/components/parameters/Condition"
          },
          {
            "$ref": "#/components/parameters/Attr"
          },
          {
            "$ref": "#/components/parameters/MinPrice"
          },
          {
            "$ref": "#/components/parameters/MaxPrice"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "$ref": "#/components/parameters/MaxPages"
          },
          {
            "$ref": "#/components/parameters/Details"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl \"https://api.trawl.dev/ebay/v1/sold?query=iphone+15+pro+256gb&condition=used&exclude=case,cracked&max_pages=5\" \\\n  -H \"x-api-key: $TRAWL_API_KEY\"\n"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from trawl_api import Trawl\n\nclient = Trawl()  # reads TRAWL_API_KEY\nsold = client.ebay.sold(\n    \"iphone 15 pro 256gb\",\n    condition=\"used\",\n    exclude=[\"case\", \"cracked\"],\n    max_pages=5,\n)\n"
          },
          {
            "lang": "javascript",
            "label": "Node",
            "source": "import { Trawl } from 'trawl-api'\n\nconst client = new Trawl() // reads TRAWL_API_KEY\nconst sold = await client.ebay.sold('iphone 15 pro 256gb', {\n  condition: 'used',\n  exclude: ['case', 'cracked'],\n  max_pages: 5,\n})\n"
          }
        ],
        "responses": {
          "200": {
            "description": "The search ran. `results` holds the matching sales, newest first, and is empty when nothing matched.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Credits-Charged": {
                "$ref": "#/components/headers/X-Credits-Charged"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SoldResponse"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/SoldDefault"
                  },
                  "with_details": {
                    "$ref": "#/components/examples/SoldWithDetails"
                  },
                  "no_results": {
                    "$ref": "#/components/examples/SoldNoResults"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/ebay/v1/item": {
      "get": {
        "operationId": "item",
        "tags": [
          "eBay"
        ],
        "summary": "Get one listing's details",
        "description": "Returns the page-level data of one sold listing: every item specific, the\ndescription, all images, the seller, shipping service and returns policy,\nplus the listing's recorded sales.\n\n**Cost.** 1 credit when the details are returned.\n\n**Removed listings.** When eBay has taken the listing down, the response\nis a `200` that carries only `site`, `item_id`, `listing_state` set to\n`removed` and `credits_charged` set to `0`. That answer is final; check\n`listing_state` before reading any other field.\n\n**Details not available yet.** A listing's details become available a few\nminutes after its sale is recorded. Until then the response is `404`,\nwhich is not charged; request the item again later.\n\n**Reading the sale.** Every `item_id` returned by the sold-listings search\nhas sold at least once. `listing_state` reports what the listing showed\nwhen its details were recorded, so `active` and `ended_unsold` do not mean\nthe item is unsold: on those, `sold_at`, `sale_price` and\n`best_offer_accepted` are `null`, and the dates and prices of the sales\nare in `sales`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "$ref": "#/components/parameters/ItemSite"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl \"https://api.trawl.dev/ebay/v1/item?item_id=256637082114\" \\\n  -H \"x-api-key: $TRAWL_API_KEY\"\n"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from trawl_api import Trawl\n\nclient = Trawl()  # reads TRAWL_API_KEY\nitem = client.ebay.item(\"256637082114\")\n"
          },
          {
            "lang": "javascript",
            "label": "Node",
            "source": "import { Trawl } from 'trawl-api'\n\nconst client = new Trawl() // reads TRAWL_API_KEY\nconst item = await client.ebay.item('256637082114')\n"
          }
        ],
        "responses": {
          "200": {
            "description": "The listing's details, or the statement that eBay has removed the listing.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Credits-Charged": {
                "$ref": "#/components/headers/X-Credits-Charged"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemResponse"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ItemDefault"
                  },
                  "removed": {
                    "$ref": "#/components/examples/ItemRemoved"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "404": {
            "$ref": "#/components/responses/ItemDetailsNotAvailable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/ebay/v1/categories": {
      "get": {
        "operationId": "categories",
        "tags": [
          "eBay"
        ],
        "summary": "Look up categories",
        "description": "Finds eBay leaf categories by name and returns them busiest first. Use a\nreturned `categoryId` as the `category` filter of the sold-listings\nsearch.\n\nEvery word of `query` must appear, in any order; matching is case- and\naccent-insensitive and forgives a trailing plural (`cards` matches\n`Card`). A `query` made only of digits is an id lookup instead: it returns\nthat exact category, leaf or parent, with a `leaf` flag.\n\nCategory ids differ between marketplaces, so pass the same `site` you will\nsearch with. eBay's category tree has no per-brand categories; to narrow\nto a brand, combine a generic category id with brand words in the\nsearch `query`.\n\n**Cost.** 1 credit when at least one category is returned, nothing when\nnone match. At most 200 categories are returned; when `total` is greater\nthan `count`, narrow the query.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/CategoryQuery"
          },
          {
            "$ref": "#/components/parameters/CategorySite"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl \"https://api.trawl.dev/ebay/v1/categories?query=trading+card+singles\" \\\n  -H \"x-api-key: $TRAWL_API_KEY\"\n"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "from trawl_api import Trawl\n\nclient = Trawl()  # reads TRAWL_API_KEY\nfound = client.ebay.categories(\"trading card singles\")\n"
          },
          {
            "lang": "javascript",
            "label": "Node",
            "source": "import { Trawl } from 'trawl-api'\n\nconst client = new Trawl() // reads TRAWL_API_KEY\nconst found = await client.ebay.categories('trading card singles')\n"
          }
        ],
        "responses": {
          "200": {
            "description": "The matching categories, busiest first. `categories` is empty when nothing matched.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Credits-Charged": {
                "$ref": "#/components/headers/X-Credits-Charged"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CategoriesResponse"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/CategoriesDefault"
                  },
                  "id_lookup": {
                    "$ref": "#/components/examples/CategoriesIdLookup"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "tags": [
          "Status"
        ],
        "summary": "Check the API and how current its data is",
        "description": "Reports whether the API is up and how current its data is: the newest\nsale that can be searched, on one marketplace or in one leaf category,\nand when Trawl collected it. Point an uptime monitor at it: the status is\n`200` when every product answered and `503` when one did not.\n\n**Cost.** Free. It needs an API key but spends no credits, still answers\nwhen the account's credits are spent, does not count toward the plan's\nper-second rate and does not appear in the account's usage. It allows 1\nrequest per second per account.\n\n**Parameters.** `site` and `category` are the only ones it takes; any\nother answers `400` with an error naming it.\n\n`last_sale_at` is when the newest searchable sale happened on eBay, and\n`last_scraped_at` is when Trawl collected that same sale; the gap\nbetween them is how far behind eBay collection ran. Without a\n`category`, the answer covers the whole marketplace, where something\nsells every minute, so both stay within minutes of now. With one, an old\n`last_sale_at` may only mean that nothing has sold in that category\nlately.\n",
        "parameters": [
          {
            "name": "site",
            "in": "query",
            "required": false,
            "description": "The marketplace to report on. Category ids are specific to it. The\nvalue is case-insensitive.\n",
            "schema": {
              "$ref": "#/components/schemas/Site"
            },
            "example": "EBAY_US"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Reports on one eBay leaf category instead of the whole marketplace,\ngiven as its numeric id. The rule is the sold-listings search's: an\nunknown id, an id from another marketplace or a parent category\nanswers `400`.\n",
            "schema": {
              "type": "string",
              "pattern": "^\\d+$"
            },
            "example": "261328"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl \"https://api.trawl.dev/health?category=261328\" \\\n  -H \"x-api-key: $TRAWL_API_KEY\"\n"
          }
        ],
        "responses": {
          "200": {
            "description": "Every product answered. Not charged.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Credits-Charged": {
                "$ref": "#/components/headers/X-Credits-Charged"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/HealthDefault"
                  },
                  "category": {
                    "$ref": "#/components/examples/HealthCategory"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "429": {
            "description": "More than 1 request in a second from this account. Wait the `Retry-After` seconds and retry. Not charged.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Credits-Charged": {
                "$ref": "#/components/headers/X-Credits-Charged"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_exceeded": {
                    "summary": "More than 1 request a second",
                    "value": {
                      "error": "rate limit exceeded — /health allows 1 request/second. Slow down and retry."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "A product could not be reached: the body is the health answer, with\n`ok` set to `false` on the API and on the product. Or the key could not\nbe checked, which answers the usual error object. Not charged.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/HealthResponse"
                    },
                    {
                      "$ref": "#/components/schemas/Error"
                    }
                  ]
                },
                "examples": {
                  "down": {
                    "$ref": "#/components/examples/HealthDown"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "The account's API key, sent in the `x-api-key` request header. Keys start\nwith `sk_` and are created at https://trawl.dev/console/keys. A missing,\ninvalid or revoked key answers `403`.\n"
      }
    },
    "parameters": {
      "Query": {
        "name": "query",
        "in": "query",
        "required": false,
        "description": "Words that must all appear in the listing title, in any order. Matching is\non whole words and is case- and accent-insensitive; the text is split into\nwords on every non-alphanumeric character. At most 32 distinct words are\naccepted. Required unless `category` is sent: a request with neither\nanswers `400`; with a `category` and no `query`, every sale in the\ncategory is returned.\n",
        "schema": {
          "type": "string",
          "minLength": 1
        },
        "example": "iphone 15 pro 256gb"
      },
      "Site": {
        "name": "site",
        "in": "query",
        "required": false,
        "description": "The marketplace to search. Each marketplace is searched separately; prices\nare in that marketplace's own currency and category ids are specific to\nit. The value is case-insensitive.\n",
        "schema": {
          "$ref": "#/components/schemas/Site"
        },
        "example": "EBAY_US"
      },
      "ItemSite": {
        "name": "site",
        "in": "query",
        "required": false,
        "description": "The marketplace the item sold on. The value is case-insensitive.",
        "schema": {
          "$ref": "#/components/schemas/Site"
        },
        "example": "EBAY_US"
      },
      "CategorySite": {
        "name": "site",
        "in": "query",
        "required": false,
        "description": "The marketplace whose category tree to search. Category ids are not\ninterchangeable between marketplaces. The value is case-insensitive.\n",
        "schema": {
          "$ref": "#/components/schemas/Site"
        },
        "example": "EBAY_US"
      },
      "Exclude": {
        "name": "exclude",
        "in": "query",
        "required": false,
        "description": "Words that must not appear in the listing title, separated by commas or\nspaces. Each word is matched on its own, as a whole word. At most 32\ndistinct words are accepted, and none of them may also be in `query`.\n",
        "schema": {
          "type": "string"
        },
        "example": "case,cracked"
      },
      "Category": {
        "name": "category",
        "in": "query",
        "required": false,
        "description": "Restricts results to one eBay leaf category, given as its numeric id. The\nid must exist in the category tree of the chosen `site` and must be a leaf\ncategory; an unknown id, an id from another marketplace or a parent\ncategory answers `400`. Look ids up with `GET /ebay/v1/categories`. On\nits own, with no `query`, it returns every sale in the category, newest\nfirst; `cursor` walks the whole of it.\n",
        "schema": {
          "type": "string",
          "pattern": "^\\d+$"
        },
        "example": "9355"
      },
      "Condition": {
        "name": "condition",
        "in": "query",
        "required": false,
        "description": "Restricts results to one or more conditions, comma-separated. A listing\nmatches when its `condition` is any of the given values. Values are\ncase-insensitive.\n",
        "style": "form",
        "explode": false,
        "schema": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "$ref": "#/components/schemas/Condition"
          }
        },
        "example": [
          "used"
        ]
      },
      "Attr": {
        "name": "attr",
        "in": "query",
        "required": false,
        "description": "Filters on an item specific, written `Key:Value` and split at the first\ncolon. The match is exact on the whole value and is case-, accent- and\nwhitespace-insensitive. Repeat the parameter for several filters:\ndifferent keys must all match, and repeating one key matches any of its\nvalues (`attr=Grade:9&attr=Grade:10` is grade 9 or 10). At most 16 `attr`\nparameters are accepted in total. Only listings whose details are\navailable have item specifics, so any `attr` filter limits results to\nthose listings. The filter changes which listings match, not the shape of\nthe response.\n",
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "maxItems": 16,
          "items": {
            "type": "string",
            "pattern": "^[^:]+:.+$"
          }
        },
        "example": [
          "Brand:Apple",
          "Storage Capacity:256 GB"
        ]
      },
      "MinPrice": {
        "name": "min_price",
        "in": "query",
        "required": false,
        "description": "Minimum sale price, inclusive, in the marketplace's own currency (USD on\n`EBAY_US`, GBP on `EBAY_GB`). No currency conversion is done. Must be\nless than or equal to `max_price` when both are set.\n",
        "schema": {
          "type": "number",
          "minimum": 0
        },
        "example": 300
      },
      "MaxPrice": {
        "name": "max_price",
        "in": "query",
        "required": false,
        "description": "Maximum sale price, inclusive, in the marketplace's own currency.",
        "schema": {
          "type": "number",
          "minimum": 0
        },
        "example": 900
      },
      "DateFrom": {
        "name": "date_from",
        "in": "query",
        "required": false,
        "description": "Earliest sale date, inclusive, as `YYYY-MM-DD` on the marketplace's own\ncalendar. Must be a real calendar date and must not be later than\n`date_to` when both are set.\n",
        "schema": {
          "type": "string",
          "format": "date"
        },
        "example": "2026-07-01"
      },
      "DateTo": {
        "name": "date_to",
        "in": "query",
        "required": false,
        "description": "Latest sale date, inclusive, as `YYYY-MM-DD` on the marketplace's own calendar. Must be a real calendar date.",
        "schema": {
          "type": "string",
          "format": "date"
        },
        "example": "2026-09-30"
      },
      "MaxPages": {
        "name": "max_pages",
        "in": "query",
        "required": false,
        "description": "How many pages of 100 results to return, all in this one response. It is\nalso the most credits the request can cost: the charge is 1 credit per\npage of results actually returned, or 2 per page with `details`. A value\noutside 1 to 20, or one that is not a whole number, answers `400`. When\nthe parameter is omitted one page is returned, reported as `max_pages` 1.\n",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 20,
          "default": 1
        },
        "example": 5
      },
      "Details": {
        "name": "details",
        "in": "query",
        "required": false,
        "description": "Set to `1` or `true` to include each result's full listing details: a\n`details` object per result, identical to the response of\n`GET /ebay/v1/item` for that `item_id`. This is also how to get the\naccepted amount of a Best Offer sale: the search's own `sale_price` is\nthe listed price, and `details.sale_price` is the accepted amount where\neBay publishes it (Collectibles categories). The search then costs 2 credits\nper page of results returned instead of 1, and results are limited to\nlistings whose details are available and listings eBay has removed, so\nfewer results are returned than for the same search without it. `0`,\n`false` or an empty value leaves details off; any other value answers\n`400`.\n",
        "schema": {
          "type": "boolean",
          "default": false
        },
        "example": false
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "The `next_cursor` of a previous response, sent back unchanged to continue\nthat search from exactly where it stopped. The search must be the same —\n`site`, `query`, `exclude`, `category`, prices, dates, `condition`, `attr`\nand `details` — or the request answers `400`; `max_pages` may differ. It\ncannot be combined with `page`. A cursor is a position, not a session:\nnothing is stored server-side and it does not expire. A request with a\ncursor is priced like any other, and one that finds nothing more costs\nnothing.\n",
        "schema": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_-]+$"
        },
        "example": "WzEsMTc4NTk3NDQwMDAwMCwiMzY2NTYxMDU0MTM0IiwiNmYyYTFiOWM0ZDA3Il0"
      },
      "ItemId": {
        "name": "item_id",
        "in": "query",
        "required": true,
        "description": "The numeric eBay item id of the listing, 9 to 15 digits. It is the `item_id` of any sold-listings search result.",
        "schema": {
          "type": "string",
          "pattern": "^\\d{9,15}$"
        },
        "example": "256637082114"
      },
      "CategoryQuery": {
        "name": "query",
        "in": "query",
        "required": true,
        "description": "Words to match against category names; every word must appear, in any\norder. Matching is case- and accent-insensitive. Only the first 12 words\nare used. A value made only of digits is treated as a category id and\nreturns that exact category.\n",
        "schema": {
          "type": "string",
          "minLength": 1
        },
        "example": "trading card singles"
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Credits included in the account's plan per billing window, including any bonus credits granted for the current window.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 15000
      },
      "X-RateLimit-Remaining": {
        "description": "Credits left in the current billing window after this response. Never below 0.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 14212
      },
      "X-RateLimit-Reset": {
        "description": "When the current billing window ends and the allowance resets, as a Unix timestamp in seconds.",
        "schema": {
          "type": "integer"
        },
        "example": 1793491200
      },
      "X-Credits-Charged": {
        "description": "Credits this response cost. The same number as `credits_charged` in the body of a successful response, and `0` on every error.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 1
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying. Present only when the per-second rate was exceeded; a `429` without this header means the account does not have enough credits for the request.",
        "schema": {
          "type": "integer"
        },
        "example": 1
      }
    },
    "responses": {
      "BadRequest": {
        "description": "A parameter failed validation. The message names the parameter and the rule it broke. Not charged.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/X-Credits-Charged"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "price_range": {
                "summary": "min_price is greater than max_price",
                "value": {
                  "error": "min_price must be <= max_price"
                }
              },
              "invalid_condition": {
                "summary": "An unknown condition value",
                "value": {
                  "error": "condition \"mint\" is not valid — use: new, used, parts, other"
                }
              },
              "invalid_max_pages": {
                "summary": "max_pages outside 1 to 20",
                "value": {
                  "error": "max_pages must be a whole number, 1-20"
                }
              }
            }
          }
        }
      },
      "InvalidApiKey": {
        "description": "The `x-api-key` header is missing, or the key is invalid, revoked or belongs to a closed account. Rate-limit headers are not sent on this response.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "missing_key": {
                "summary": "No key was sent",
                "value": {
                  "error": "unauthorized — send a valid x-api-key"
                }
              },
              "invalid_key": {
                "summary": "The key is not valid",
                "value": {
                  "error": "unauthorized — API key is invalid or revoked"
                }
              }
            }
          }
        }
      },
      "ItemDetailsNotAvailable": {
        "description": "The listing's details are not available yet. They usually follow within minutes of a sale; request the item again later. Not charged.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/X-Credits-Charged"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "not_available_yet": {
                "summary": "Details have not been recorded yet",
                "value": {
                  "error": "item details not available yet — they usually follow within minutes of a sale; try again shortly"
                }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "The request was refused and not charged. There are two cases, told apart\nby the `Retry-After` header. With `Retry-After`, the account's per-second\nrate was exceeded: wait that many seconds and retry. Without it, the\naccount's monthly credits are spent, or too few remain to cover the most\nthe request could cost: lower `max_pages`, wait for the time in\n`X-RateLimit-Reset`, or change plan. Retrying without one of those does\nnot help.\n",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/X-Credits-Charged"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "rate_exceeded": {
                "summary": "Per-second rate exceeded (sent with Retry-After)",
                "value": {
                  "error": "rate limit exceeded — your plan allows 5 requests/second. Slow down and retry."
                }
              },
              "credits_spent": {
                "summary": "Monthly credits spent (no Retry-After)",
                "value": {
                  "error": "monthly limit reached — your plan includes 15000 credits/month. Upgrade at https://trawl.dev/console/billing"
                }
              },
              "not_enough_credits": {
                "summary": "Too few credits left for this request (no Retry-After)",
                "value": {
                  "error": "not enough credits — this request can cost up to 5 credits and 3 of your 15000 credits/month remain. Lower max_pages to 3 or less, or upgrade at https://trawl.dev/console/billing"
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "An internal error. Not charged.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "internal_error": {
                "summary": "Internal error",
                "value": {
                  "error": "internal error"
                }
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The service is temporarily unavailable, or the request took longer than 30 seconds. Not charged. Safe to retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "api_unavailable": {
                "summary": "The eBay API could not be reached in time",
                "value": {
                  "error": "the ebay API is temporarily unavailable — try again shortly"
                }
              },
              "search_unavailable": {
                "summary": "The search backend is unavailable",
                "value": {
                  "error": "search backend unavailable"
                }
              },
              "accounts_unavailable": {
                "summary": "The key could not be checked",
                "value": {
                  "error": "account backend unavailable — try again shortly"
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "The body of every error response.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "What went wrong, in plain language. For a validation error it names the parameter and the rule it broke."
          }
        }
      },
      "Site": {
        "type": "string",
        "description": "An eBay marketplace. `EBAY_US` is ebay.com, with prices in USD. `EBAY_GB` is ebay.co.uk, with prices in GBP.",
        "enum": [
          "EBAY_US",
          "EBAY_GB"
        ],
        "default": "EBAY_US"
      },
      "Condition": {
        "type": "string",
        "description": "The normalized condition of a listing. `new` covers Brand New, New with\ntags or box, New (Other), New with defects and Open box. `used` covers\nPre-Owned in all grades, Like New, Very Good, Good, Acceptable, every\nRefurbished tier, Remanufactured, Graded and Ungraded. `parts` covers For\nparts or not working, and Damaged. `other` covers digital goods and\nlistings for which eBay showed no usable condition.\n",
        "enum": [
          "new",
          "used",
          "parts",
          "other"
        ]
      },
      "SoldResponse": {
        "type": "object",
        "description": "The response of a sold-listings search.",
        "required": [
          "site",
          "currency",
          "query",
          "filters",
          "count",
          "took_ms",
          "results",
          "credits_charged"
        ],
        "properties": {
          "site": {
            "$ref": "#/components/schemas/Site",
            "description": "The marketplace that was searched."
          },
          "currency": {
            "type": "string",
            "description": "The ISO 4217 code of the marketplace's currency, in which `min_price`, `max_price` and each result's prices are expressed. `USD` on `EBAY_US`, `GBP` on `EBAY_GB`."
          },
          "query": {
            "type": "array",
            "description": "The words of `query` as they were searched, lowercased, accent-folded and de-duplicated.",
            "items": {
              "type": "string"
            }
          },
          "exclude": {
            "type": "array",
            "description": "The words of `exclude` as they were applied. Present only when `exclude` was sent.",
            "items": {
              "type": "string"
            }
          },
          "filters": {
            "$ref": "#/components/schemas/SoldFilters"
          },
          "details": {
            "type": "boolean",
            "description": "Present, and `true`, only when the request set `details`."
          },
          "page": {
            "type": "integer",
            "description": "Present, in place of `max_pages` and `next_cursor`, only when the request used the original one-page `page` parameter."
          },
          "max_pages": {
            "type": "integer",
            "description": "The `max_pages` value of the request, `1` when it was not sent."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "A cursor to continue this search with, as the `cursor` parameter, when the response is full (`count` equals `max_pages` × 100) and more may exist. `null` when the search reached its end."
          },
          "count": {
            "type": "integer",
            "description": "The number of entries in `results`. When it equals the number of results requested (`max_pages` × 100), more matching sales may exist — `next_cursor` continues."
          },
          "took_ms": {
            "type": "integer",
            "description": "Server-side time spent running the search, in milliseconds."
          },
          "results": {
            "type": "array",
            "description": "The matching sales, newest first. Empty when nothing matched.",
            "items": {
              "$ref": "#/components/schemas/SoldListing"
            }
          },
          "credits_charged": {
            "type": "integer",
            "description": "Credits this response cost. 1 per page of results returned, 2 per page with `details`, and 0 when `results` is empty."
          }
        }
      },
      "SoldFilters": {
        "type": "object",
        "description": "The filters that were applied, echoed so a caller can confirm each parameter was understood. A filter that was not sent has no key; with no filters the object is empty.",
        "properties": {
          "category": {
            "type": "string",
            "description": "The category id that was filtered on."
          },
          "category_name": {
            "type": "string",
            "description": "The name of that category in the searched marketplace's category tree."
          },
          "min_price": {
            "type": "number",
            "description": "The minimum sale price that was applied."
          },
          "max_price": {
            "type": "number",
            "description": "The maximum sale price that was applied."
          },
          "date_from": {
            "type": "string",
            "format": "date",
            "description": "The earliest sale date that was applied."
          },
          "date_to": {
            "type": "string",
            "format": "date",
            "description": "The latest sale date that was applied."
          },
          "condition": {
            "type": "array",
            "description": "The condition values that were applied.",
            "items": {
              "$ref": "#/components/schemas/Condition"
            }
          },
          "attr": {
            "type": "object",
            "description": "The item-specific filters that were applied, keyed by the normalized (lowercased, accent-folded) key. A key filtered on one value maps to a string, and a key filtered on several values maps to an array of strings.",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ]
            }
          }
        }
      },
      "SoldListing": {
        "type": "object",
        "description": "One sale of one listing.",
        "required": [
          "title",
          "sale_price",
          "shipping_price",
          "currency",
          "condition",
          "condition_raw",
          "date_sold",
          "buying_format",
          "item_id",
          "categoryId",
          "item_link",
          "image_url"
        ],
        "properties": {
          "title": {
            "type": "string",
            "description": "The listing title."
          },
          "sale_price": {
            "type": "number",
            "description": "The price the item sold for, in the marketplace's currency, excluding shipping. For a sale that closed on an accepted Best Offer this is the listed price, because eBay's sold results do not show the accepted amount. To get the accepted amount, pass `details=1` and read `details.sale_price` where `details.best_offer_accepted` is `true`; eBay publishes it on Collectibles listings (trading cards, comics, coins and the like) and on no other category, where every source has only the listed price. On `EBAY_GB` it is the price a UK buyer saw and paid, which for a private seller includes eBay's Buyer Protection fee."
          },
          "shipping_price": {
            "type": [
              "number",
              "null"
            ],
            "description": "The shipping cost the buyer paid, in the marketplace's currency. `0` for free shipping, `null` when it is not known."
          },
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "The currency symbol of the prices, as eBay prints it, for example `$` or `£`. The ISO code is in the response's top-level `currency`."
          },
          "condition": {
            "$ref": "#/components/schemas/Condition",
            "description": "The normalized condition. It takes the same values as the `condition` filter, so it can be passed back as one."
          },
          "condition_raw": {
            "type": [
              "string",
              "null"
            ],
            "description": "eBay's own wording for the condition, verbatim, for example `Pre-Owned` or `New (Other)`. `null` when eBay showed no condition. Trading cards and coins read `Pre-Owned` here; their card condition, grader and grade are in the listing details."
          },
          "date_sold": {
            "type": "string",
            "format": "date-time",
            "description": "When the item sold, on the marketplace's own calendar (Pacific time for `EBAY_US`, UK time for `EBAY_GB`). The trailing `Z` is nominal; read the value as marketplace-local wall-clock time, not as a UTC instant. The time of day is included when eBay exposes it; sales recorded before September 2026 and sales from multi-quantity listings carry the day only, as midnight."
          },
          "buying_format": {
            "type": [
              "string",
              "null"
            ],
            "description": "How the item was sold, as eBay labels it, for example `Buy It Now`, `Auction` or `Best Offer`."
          },
          "bids": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The number of bids on an auction. `null` for fixed-price listings. May be absent on older sales."
          },
          "best_offer_available": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the listing accepted Best Offers. May be absent on older sales."
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "The item's location as eBay shows it in sold results, for example `United States`. ebay.com names a country on every sale; ebay.co.uk shows a location only for items outside the UK, so a blank value there is a UK item. May be absent on older sales."
          },
          "location_country": {
            "type": [
              "string",
              "null"
            ],
            "description": "The country the location resolves to, the same value on every marketplace, for example `United States`, `United Kingdom` or `Canada`. On `EBAY_GB` a blank `location` resolves to `United Kingdom` for sales recorded from September 2026; a blank on an older sale is `null`."
          },
          "item_id": {
            "type": "string",
            "description": "The eBay item id of the listing. Pass it to `GET /ebay/v1/item` for the listing's details."
          },
          "epid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The eBay product id (ePID) of the catalog product the listing is matched to. `null` when the listing has none. May be absent on older sales."
          },
          "categoryId": {
            "type": "string",
            "description": "The id of the leaf category the listing was sold in."
          },
          "item_link": {
            "type": "string",
            "format": "uri",
            "description": "The URL of the listing on eBay."
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The URL of the listing's primary image."
          },
          "details": {
            "description": "The listing's details. Present only when the request set `details`. It is the listing object that `GET /ebay/v1/item` returns for this `item_id`, or the removed-listing object when eBay has taken the listing down, or in rare cases `null` when the details could not be read at the time of the request.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Listing"
              },
              {
                "$ref": "#/components/schemas/RemovedListing"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Listing": {
        "type": "object",
        "description": "The page-level data of one listing, with its recorded sales.",
        "required": [
          "site",
          "item_id",
          "title",
          "condition",
          "condition_raw",
          "condition_description",
          "grading",
          "listing_state",
          "sold_at",
          "last_updated",
          "sale_price",
          "list_price",
          "currency",
          "buying_format",
          "bids",
          "best_offer_available",
          "best_offer_accepted",
          "shipping_service",
          "returns_text",
          "seller_accepts_returns",
          "location",
          "location_country",
          "epid",
          "categoryId",
          "item_link",
          "images",
          "attributes",
          "description_url",
          "description_text",
          "seller",
          "feedback",
          "sales"
        ],
        "properties": {
          "site": {
            "$ref": "#/components/schemas/Site",
            "description": "The marketplace the listing belongs to."
          },
          "item_id": {
            "type": "string",
            "description": "The eBay item id of the listing."
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "The listing title."
          },
          "condition": {
            "$ref": "#/components/schemas/Condition",
            "description": "The normalized condition, derived from the condition shown on the listing page."
          },
          "condition_raw": {
            "type": [
              "string",
              "null"
            ],
            "description": "The condition as the listing page words it, verbatim. For trading cards and coins this is the full line, for example `Graded - PSA 10` or `Ungraded - Near mint or better`. `null` when the page showed none."
          },
          "condition_description": {
            "type": [
              "string",
              "null"
            ],
            "description": "The seller's own note about the item's condition."
          },
          "grading": {
            "description": "The grading of a trading card or coin, split out of `condition_raw`. `null` for every other kind of item.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/Grading"
              },
              {
                "type": "null"
              }
            ]
          },
          "listing_state": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "sold",
              "active",
              "ended_unsold",
              null
            ],
            "description": "What the listing page showed when its details were recorded. `sold` means the page showed the sale. `active` means the listing was still live, usually a multi-quantity listing with stock left or a relisted item. `ended_unsold` means the listing had ended without the page showing a sale. In all three cases the item has sold at least once, and the sales are in `sales`."
          },
          "sold_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The instant the listing sold, in UTC, as shown on the listing page. `null` unless `listing_state` is `sold`; use `sales[].date_sold` otherwise."
          },
          "last_updated": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the seller last revised the listing, as shown on the listing page."
          },
          "sale_price": {
            "type": [
              "number",
              "null"
            ],
            "description": "The price the item sold for, as shown on the listing page, in the page's `currency`. `null` unless `listing_state` is `sold`; use `sales[].sale_price` otherwise. When `best_offer_accepted` is `true` this is the accepted offer amount on categories where eBay publishes it, and the listed price elsewhere. On `EBAY_GB`, for a listing priced in pounds whose sale did not close on an accepted offer, this is the price of the recorded sale, so it agrees with the sold-listings search."
          },
          "list_price": {
            "type": [
              "number",
              "null"
            ],
            "description": "The higher asking price a lower `sale_price` was struck through against, in the same `currency`. When `best_offer_accepted` is `true` it is the asking price the accepted offer was bargained down from; on a marked-down listing it is the \"was\" price. `null` when there is no second price. Present on sales recorded from 2026-10-29; earlier sales read `null`."
          },
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "The currency of `sale_price` as the listing page prints it, for example `US$` or `£`."
          },
          "buying_format": {
            "type": [
              "string",
              "null"
            ],
            "description": "How the item was sold, as eBay labels it, for example `Buy It Now` or `Auction`."
          },
          "bids": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The number of bids on an auction. `null` for fixed-price listings."
          },
          "best_offer_available": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the listing accepted Best Offers."
          },
          "best_offer_accepted": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the sale closed on an accepted Best Offer. `null` unless `listing_state` is `sold`."
          },
          "shipping_service": {
            "type": [
              "string",
              "null"
            ],
            "description": "The shipping service named on the listing page, for example `USPS Ground Advantage`. The shipping cost the buyer paid is `shipping_price` on each entry of `sales`."
          },
          "returns_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "The returns policy as worded on the listing page."
          },
          "seller_accepts_returns": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the seller accepts returns."
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "The item's location as shown on the listing page, for example `Austin, Texas`."
          },
          "location_country": {
            "type": [
              "string",
              "null"
            ],
            "description": "The country part of the item's location."
          },
          "epid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The eBay product id (ePID) of the catalog product the listing is matched to. `null` when the listing has none."
          },
          "categoryId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The id of the leaf category the listing is in."
          },
          "item_link": {
            "type": "string",
            "format": "uri",
            "description": "The URL of the listing on eBay."
          },
          "images": {
            "type": "array",
            "description": "The URLs of every image on the listing page, in page order. Empty when there are none.",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "attributes": {
            "type": "array",
            "description": "The listing's item specifics, in page order. Empty when there are none.",
            "items": {
              "$ref": "#/components/schemas/ItemSpecific"
            }
          },
          "description_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The URL of the listing's description document on eBay."
          },
          "description_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "The listing description as plain text."
          },
          "seller": {
            "description": "The seller of the listing. `null` when the page showed no seller.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/Seller"
              },
              {
                "type": "null"
              }
            ]
          },
          "feedback": {
            "type": "array",
            "description": "Recent feedback left for the seller, as shown on the listing page. Empty when there is none.",
            "items": {
              "$ref": "#/components/schemas/SellerFeedback"
            }
          },
          "sales": {
            "type": "array",
            "description": "The recorded sales of this listing, newest first, at most 100. A listing that sold on several days has one entry per sale. These are the dates and prices to use when `listing_state` is not `sold`.",
            "items": {
              "$ref": "#/components/schemas/ListingSale"
            }
          }
        }
      },
      "RemovedListing": {
        "type": "object",
        "description": "The whole answer for a listing eBay has taken down. It carries no sale data and no details.",
        "required": [
          "site",
          "item_id",
          "listing_state"
        ],
        "properties": {
          "site": {
            "$ref": "#/components/schemas/Site",
            "description": "The marketplace the listing belonged to."
          },
          "item_id": {
            "type": "string",
            "description": "The eBay item id of the listing."
          },
          "listing_state": {
            "type": "string",
            "const": "removed",
            "description": "Always `removed`. eBay has taken the listing down, so there are no details to return and the answer is final."
          }
        }
      },
      "ItemResponse": {
        "description": "The response of a listing lookup. Either the listing's details, or the removed-listing object; check `listing_state` to tell which.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/ItemDetailsResponse"
          },
          {
            "$ref": "#/components/schemas/RemovedItemResponse"
          }
        ]
      },
      "ItemDetailsResponse": {
        "description": "A listing's details and what the response cost.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Listing"
          },
          {
            "type": "object",
            "required": [
              "credits_charged"
            ],
            "properties": {
              "credits_charged": {
                "type": "integer",
                "description": "Credits this response cost. Always 1 when details are returned."
              }
            }
          }
        ]
      },
      "RemovedItemResponse": {
        "description": "The response for a listing eBay has removed.",
        "allOf": [
          {
            "$ref": "#/components/schemas/RemovedListing"
          },
          {
            "type": "object",
            "required": [
              "credits_charged"
            ],
            "properties": {
              "credits_charged": {
                "type": "integer",
                "description": "Credits this response cost. Always 0 for a removed listing."
              }
            }
          }
        ]
      },
      "Grading": {
        "type": "object",
        "description": "The grading of a trading card or coin.",
        "required": [
          "graded",
          "grader",
          "grade",
          "condition"
        ],
        "properties": {
          "graded": {
            "type": "boolean",
            "description": "`true` for a professionally graded item (a slab), `false` for an ungraded one."
          },
          "grader": {
            "type": [
              "string",
              "null"
            ],
            "description": "The grading company as eBay abbreviates it, for example `PSA`, `CGC` or `BGS`. Set on graded items only. When the condition line does not end in a recognizable grade, its whole remainder is placed here and `grade` is `null`."
          },
          "grade": {
            "type": [
              "string",
              "null"
            ],
            "description": "The grade as printed, for example `10`, `9.5` or `Authentic`. Set on graded items only."
          },
          "condition": {
            "type": [
              "string",
              "null"
            ],
            "description": "The seller-declared condition of an ungraded item, for example `Near mint or better`, or `Uncirculated` for a coin. `null` on graded items."
          }
        }
      },
      "ItemSpecific": {
        "type": "object",
        "description": "One item specific of a listing.",
        "required": [
          "key"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "The name of the item specific as the seller's listing shows it, for example `Brand` or `Storage Capacity`."
          },
          "value": {
            "type": "string",
            "description": "The value as displayed on the listing page. When the seller gave several values this is the joined display string, for example `Magnet, PP, Rubber`."
          },
          "values": {
            "type": "array",
            "description": "Every value given for this item specific, one entry each.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Seller": {
        "type": "object",
        "description": "The seller of a listing, as shown on the listing page.",
        "properties": {
          "username": {
            "type": "string",
            "description": "The seller's eBay username."
          },
          "feedback_percent": {
            "type": [
              "number",
              "null"
            ],
            "description": "The seller's positive-feedback percentage, from 0 to 100."
          },
          "feedback_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The seller's feedback count."
          },
          "items_sold": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The number of items the seller has sold, when the listing page shows it."
          }
        }
      },
      "SellerFeedback": {
        "type": "object",
        "description": "One feedback entry left for the seller.",
        "properties": {
          "username": {
            "type": [
              "string",
              "null"
            ],
            "description": "The buyer's username, masked as eBay shows it, for example `b***y`."
          },
          "rating": {
            "type": [
              "string",
              "null"
            ],
            "description": "The kind of feedback, one of `positive`, `neutral` or `negative`."
          },
          "comment": {
            "type": [
              "string",
              "null"
            ],
            "description": "The text of the feedback."
          },
          "age_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "How long ago the feedback was left, as eBay words it, for example `Past month`."
          }
        }
      },
      "ListingSale": {
        "type": "object",
        "description": "One recorded sale of a listing.",
        "required": [
          "date_sold",
          "sale_price"
        ],
        "properties": {
          "date_sold": {
            "type": "string",
            "format": "date-time",
            "description": "The day of the sale on the marketplace's own calendar, written as a timestamp. The trailing `Z` is nominal."
          },
          "sale_price": {
            "type": "number",
            "description": "The price of this sale as eBay's sold results report it, in the marketplace's currency. For a sale that closed on an accepted Best Offer this is the listed price; the accepted amount, where eBay publishes it, is the top-level `sale_price` with `best_offer_accepted` `true`."
          },
          "shipping_price": {
            "type": [
              "number",
              "null"
            ],
            "description": "The shipping cost the buyer paid for this sale. `0` for free shipping."
          },
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "The currency symbol of this sale's prices, for example `$` or `£`."
          },
          "condition": {
            "type": [
              "string",
              "null"
            ],
            "description": "eBay's wording for the condition at the time of this sale, for example `Pre-Owned`."
          }
        }
      },
      "CategoriesResponse": {
        "type": "object",
        "description": "The response of a category lookup.",
        "required": [
          "site",
          "total",
          "count",
          "categories",
          "credits_charged"
        ],
        "properties": {
          "site": {
            "$ref": "#/components/schemas/Site",
            "description": "The marketplace whose category tree was searched."
          },
          "total": {
            "type": "integer",
            "description": "How many categories matched. Greater than `count` when more than 200 matched."
          },
          "count": {
            "type": "integer",
            "description": "The number of entries in `categories`, at most 200."
          },
          "categories": {
            "type": "array",
            "description": "The matching categories, busiest first. Empty when nothing matched.",
            "items": {
              "$ref": "#/components/schemas/Category"
            }
          },
          "credits_charged": {
            "type": "integer",
            "description": "Credits this response cost. 1 when at least one category is returned, 0 when none matched."
          }
        }
      },
      "Category": {
        "type": "object",
        "description": "One eBay category.",
        "required": [
          "categoryId",
          "name"
        ],
        "properties": {
          "categoryId": {
            "type": "string",
            "description": "The category id. Use it as the `category` filter of the sold-listings search, on the same `site`."
          },
          "name": {
            "type": "string",
            "description": "The category's name."
          },
          "group": {
            "type": "string",
            "description": "The name of the top-level category this category belongs to, for example `Collectibles`."
          },
          "leaf": {
            "type": "boolean",
            "description": "Whether the category is a leaf. Present only on an id lookup (a `query` made of digits). Only leaf categories can be used as the `category` filter."
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "description": "Whether the API is up, and how current each product's data is.",
        "required": [
          "ok",
          "time",
          "products"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "`true` when every product answered (status `200`), `false` when one did not (status `503`)."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "When this answer was made, in UTC."
          },
          "products": {
            "type": "object",
            "description": "One entry per product, keyed by the product's path segment.",
            "required": [
              "ebay"
            ],
            "properties": {
              "ebay": {
                "$ref": "#/components/schemas/EbayHealth"
              }
            }
          }
        }
      },
      "EbayHealth": {
        "type": "object",
        "description": "The eBay API's state, and its newest searchable sale on the chosen marketplace or in the chosen category. When `ok` is `false`, `ok` is the only field.",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "`false` when the eBay API or its search backend could not be reached."
          },
          "site": {
            "$ref": "#/components/schemas/Site"
          },
          "category": {
            "type": "string",
            "description": "The category reported on, as requested. Present only with a `category` parameter."
          },
          "category_name": {
            "type": "string",
            "description": "The category's name on this marketplace. Present only with a `category` parameter."
          },
          "last_sale_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the newest searchable sale happened on eBay, in UTC. `null` when there is none, or when its time of sale was not recorded."
          },
          "last_sale_seconds_ago": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Seconds from `last_sale_at` to this answer. `null` with it."
          },
          "last_scraped_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When Trawl collected that same sale, in UTC. `null` when there is none."
          },
          "last_scraped_seconds_ago": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Seconds from `last_scraped_at` to this answer. `null` with it."
          }
        }
      }
    },
    "examples": {
      "HealthDefault": {
        "summary": "The whole marketplace (no parameters)",
        "value": {
          "ok": true,
          "time": "2026-11-06T01:01:37.753Z",
          "products": {
            "ebay": {
              "ok": true,
              "site": "EBAY_US",
              "last_sale_at": "2026-11-06T00:54:00.000Z",
              "last_sale_seconds_ago": 457,
              "last_scraped_at": "2026-11-06T00:58:58.479Z",
              "last_scraped_seconds_ago": 159
            }
          }
        }
      },
      "HealthCategory": {
        "summary": "One leaf category (category=261328)",
        "value": {
          "ok": true,
          "time": "2026-11-06T01:01:37.787Z",
          "products": {
            "ebay": {
              "ok": true,
              "site": "EBAY_US",
              "category": "261328",
              "category_name": "Trading Card Singles",
              "last_sale_at": "2026-11-06T00:49:00.000Z",
              "last_sale_seconds_ago": 757,
              "last_scraped_at": "2026-11-06T00:55:32.053Z",
              "last_scraped_seconds_ago": 365
            }
          }
        }
      },
      "HealthDown": {
        "summary": "The eBay API could not be reached",
        "value": {
          "ok": false,
          "time": "2026-11-05T23:39:39.602Z",
          "products": {
            "ebay": {
              "ok": false
            }
          }
        }
      },
      "SoldDefault": {
        "summary": "Used iPhone 15 Pro 256GB sales, up to 5 pages requested",
        "description": "Three sales matched, which is one page, so the request cost 1 of the 5 credits `max_pages=5` allowed.",
        "value": {
          "site": "EBAY_US",
          "currency": "USD",
          "query": [
            "iphone",
            "15",
            "pro",
            "256gb"
          ],
          "exclude": [
            "case",
            "cracked"
          ],
          "filters": {
            "condition": [
              "used"
            ]
          },
          "max_pages": 5,
          "next_cursor": null,
          "count": 3,
          "took_ms": 41,
          "results": [
            {
              "title": "Apple iPhone 15 Pro 256GB Natural Titanium Unlocked A2848",
              "sale_price": 548,
              "shipping_price": 0,
              "currency": "$",
              "condition": "used",
              "condition_raw": "Pre-Owned",
              "date_sold": "2026-09-28T14:32:00.000Z",
              "buying_format": "Buy It Now",
              "bids": null,
              "best_offer_available": true,
              "location": "United States",
              "location_country": "United States",
              "item_id": "256637082114",
              "epid": "13062762640",
              "categoryId": "9355",
              "item_link": "https://www.ebay.com/itm/256637082114",
              "image_url": "https://i.ebayimg.com/images/g/k3YAAOSwq1JlXvRt/s-l500.webp"
            },
            {
              "title": "iPhone 15 Pro 256GB Blue Titanium - Unlocked - 89% Battery Health",
              "sale_price": 512.5,
              "shipping_price": 8.95,
              "currency": "$",
              "condition": "used",
              "condition_raw": "Pre-Owned",
              "date_sold": "2026-09-28T09:05:00.000Z",
              "buying_format": "Auction",
              "bids": 23,
              "best_offer_available": false,
              "location": "United States",
              "location_country": "United States",
              "item_id": "126702384915",
              "epid": "13062762640",
              "categoryId": "9355",
              "item_link": "https://www.ebay.com/itm/126702384915",
              "image_url": "https://i.ebayimg.com/images/g/9cMAAOSw2gxmQe7n/s-l500.webp"
            },
            {
              "title": "Apple iPhone 15 Pro - 256GB - Black Titanium (Verizon) Good Condition",
              "sale_price": 489.99,
              "shipping_price": 0,
              "currency": "$",
              "condition": "used",
              "condition_raw": "Good - Refurbished",
              "date_sold": "2026-09-27T00:00:00.000Z",
              "buying_format": "Buy It Now",
              "bids": null,
              "best_offer_available": false,
              "location": "United States",
              "location_country": "United States",
              "item_id": "395218840762",
              "epid": null,
              "categoryId": "9355",
              "item_link": "https://www.ebay.com/itm/395218840762",
              "image_url": "https://i.ebayimg.com/images/g/Hq4AAOSwTmFl8w0b/s-l500.webp"
            }
          ],
          "credits_charged": 1
        }
      },
      "SoldWithDetails": {
        "summary": "The same search with details=1",
        "description": "Each result carries a `details` object. The second listing has been removed by eBay, so its `details` is the removed-listing object. One page of results with details costs 2 credits.",
        "value": {
          "site": "EBAY_US",
          "currency": "USD",
          "query": [
            "iphone",
            "15",
            "pro",
            "256gb"
          ],
          "filters": {
            "condition": [
              "used"
            ]
          },
          "details": true,
          "max_pages": 1,
          "count": 2,
          "took_ms": 58,
          "results": [
            {
              "title": "Apple iPhone 15 Pro 256GB Natural Titanium Unlocked A2848",
              "sale_price": 548,
              "shipping_price": 0,
              "currency": "$",
              "condition": "used",
              "condition_raw": "Pre-Owned",
              "date_sold": "2026-09-28T14:32:00.000Z",
              "buying_format": "Buy It Now",
              "bids": null,
              "best_offer_available": true,
              "location": "United States",
              "location_country": "United States",
              "item_id": "256637082114",
              "epid": "13062762640",
              "categoryId": "9355",
              "item_link": "https://www.ebay.com/itm/256637082114",
              "image_url": "https://i.ebayimg.com/images/g/k3YAAOSwq1JlXvRt/s-l500.webp",
              "details": {
                "site": "EBAY_US",
                "item_id": "256637082114",
                "title": "Apple iPhone 15 Pro 256GB Natural Titanium Unlocked A2848",
                "condition": "used",
                "condition_raw": "Pre-Owned",
                "condition_description": "Light scratches on the frame, screen flawless. Battery health 91%.",
                "grading": null,
                "listing_state": "sold",
                "sold_at": "2026-09-28T21:32:00.000Z",
                "last_updated": "2026-09-26T18:04:11.000Z",
                "sale_price": 548,
                "list_price": null,
                "currency": "US$",
                "buying_format": "Buy It Now",
                "bids": null,
                "best_offer_available": true,
                "best_offer_accepted": false,
                "shipping_service": "USPS Ground Advantage",
                "returns_text": "30 days returns. Buyer pays for return shipping.",
                "seller_accepts_returns": true,
                "location": "Austin, Texas",
                "location_country": "United States",
                "epid": "13062762640",
                "categoryId": "9355",
                "item_link": "https://www.ebay.com/itm/256637082114",
                "images": [
                  "https://i.ebayimg.com/images/g/k3YAAOSwq1JlXvRt/s-l1600.webp",
                  "https://i.ebayimg.com/images/g/m~sAAOSwq1JlXvRu/s-l1600.webp"
                ],
                "attributes": [
                  {
                    "key": "Brand",
                    "value": "Apple",
                    "values": [
                      "Apple"
                    ]
                  },
                  {
                    "key": "Model",
                    "value": "Apple iPhone 15 Pro",
                    "values": [
                      "Apple iPhone 15 Pro"
                    ]
                  },
                  {
                    "key": "Storage Capacity",
                    "value": "256 GB",
                    "values": [
                      "256 GB"
                    ]
                  },
                  {
                    "key": "Network",
                    "value": "Unlocked",
                    "values": [
                      "Unlocked"
                    ]
                  }
                ],
                "description_url": "https://itm.ebaydesc.com/itmdesc/256637082114",
                "description_text": "Fully unlocked iPhone 15 Pro, 256GB, Natural Titanium. Battery health 91%. Comes with the original box and an unused cable.",
                "seller": {
                  "username": "phone-depot",
                  "feedback_percent": 99.6,
                  "feedback_count": 6864,
                  "items_sold": 12480
                },
                "feedback": [
                  {
                    "username": "b***y",
                    "rating": "positive",
                    "comment": "Exactly as described, fast shipping",
                    "age_text": "Past month"
                  }
                ],
                "sales": [
                  {
                    "date_sold": "2026-09-28T00:00:00.000Z",
                    "sale_price": 548,
                    "shipping_price": 0,
                    "currency": "$",
                    "condition": "Pre-Owned"
                  }
                ]
              }
            },
            {
              "title": "iPhone 15 Pro 256GB Blue Titanium - Unlocked - 89% Battery Health",
              "sale_price": 512.5,
              "shipping_price": 8.95,
              "currency": "$",
              "condition": "used",
              "condition_raw": "Pre-Owned",
              "date_sold": "2026-09-28T09:05:00.000Z",
              "buying_format": "Auction",
              "bids": 23,
              "best_offer_available": false,
              "location": "United States",
              "location_country": "United States",
              "item_id": "126702384915",
              "epid": "13062762640",
              "categoryId": "9355",
              "item_link": "https://www.ebay.com/itm/126702384915",
              "image_url": "https://i.ebayimg.com/images/g/9cMAAOSw2gxmQe7n/s-l500.webp",
              "details": {
                "site": "EBAY_US",
                "item_id": "126702384915",
                "listing_state": "removed"
              }
            }
          ],
          "credits_charged": 2
        }
      },
      "SoldNoResults": {
        "summary": "A search that matches nothing",
        "description": "A successful response with no results. It is not charged.",
        "value": {
          "site": "EBAY_US",
          "currency": "USD",
          "query": [
            "iphone",
            "15",
            "pro",
            "256gb"
          ],
          "filters": {
            "min_price": 5000
          },
          "max_pages": 1,
          "count": 0,
          "took_ms": 12,
          "results": [],
          "credits_charged": 0
        }
      },
      "ItemDefault": {
        "summary": "A sold listing's details",
        "value": {
          "site": "EBAY_US",
          "item_id": "256637082114",
          "title": "Apple iPhone 15 Pro 256GB Natural Titanium Unlocked A2848",
          "condition": "used",
          "condition_raw": "Pre-Owned",
          "condition_description": "Light scratches on the frame, screen flawless. Battery health 91%.",
          "grading": null,
          "listing_state": "sold",
          "sold_at": "2026-09-28T21:32:00.000Z",
          "last_updated": "2026-09-26T18:04:11.000Z",
          "sale_price": 548,
          "list_price": null,
          "currency": "US$",
          "buying_format": "Buy It Now",
          "bids": null,
          "best_offer_available": true,
          "best_offer_accepted": false,
          "shipping_service": "USPS Ground Advantage",
          "returns_text": "30 days returns. Buyer pays for return shipping.",
          "seller_accepts_returns": true,
          "location": "Austin, Texas",
          "location_country": "United States",
          "epid": "13062762640",
          "categoryId": "9355",
          "item_link": "https://www.ebay.com/itm/256637082114",
          "images": [
            "https://i.ebayimg.com/images/g/k3YAAOSwq1JlXvRt/s-l1600.webp",
            "https://i.ebayimg.com/images/g/m~sAAOSwq1JlXvRu/s-l1600.webp"
          ],
          "attributes": [
            {
              "key": "Brand",
              "value": "Apple",
              "values": [
                "Apple"
              ]
            },
            {
              "key": "Model",
              "value": "Apple iPhone 15 Pro",
              "values": [
                "Apple iPhone 15 Pro"
              ]
            },
            {
              "key": "Storage Capacity",
              "value": "256 GB",
              "values": [
                "256 GB"
              ]
            },
            {
              "key": "Network",
              "value": "Unlocked",
              "values": [
                "Unlocked"
              ]
            }
          ],
          "description_url": "https://itm.ebaydesc.com/itmdesc/256637082114",
          "description_text": "Fully unlocked iPhone 15 Pro, 256GB, Natural Titanium. Battery health 91%. Comes with the original box and an unused cable.",
          "seller": {
            "username": "phone-depot",
            "feedback_percent": 99.6,
            "feedback_count": 6864,
            "items_sold": 12480
          },
          "feedback": [
            {
              "username": "b***y",
              "rating": "positive",
              "comment": "Exactly as described, fast shipping",
              "age_text": "Past month"
            }
          ],
          "sales": [
            {
              "date_sold": "2026-09-28T00:00:00.000Z",
              "sale_price": 548,
              "shipping_price": 0,
              "currency": "$",
              "condition": "Pre-Owned"
            }
          ],
          "credits_charged": 1
        }
      },
      "ItemRemoved": {
        "summary": "A listing eBay has removed",
        "description": "The whole response for a removed listing. It is not charged.",
        "value": {
          "site": "EBAY_US",
          "item_id": "318172191585",
          "listing_state": "removed",
          "credits_charged": 0
        }
      },
      "CategoriesDefault": {
        "summary": "Categories matching \"trading card singles\"",
        "value": {
          "site": "EBAY_US",
          "total": 2,
          "count": 2,
          "categories": [
            {
              "categoryId": "261328",
              "name": "Trading Card Singles",
              "group": "Sports Mem, Cards & Fan Shop"
            },
            {
              "categoryId": "183050",
              "name": "Trading Card Singles",
              "group": "Collectibles"
            }
          ],
          "credits_charged": 1
        }
      },
      "CategoriesIdLookup": {
        "summary": "An id lookup (query=9355)",
        "description": "A `query` made of digits returns that exact category with its `leaf` flag.",
        "value": {
          "site": "EBAY_US",
          "total": 1,
          "count": 1,
          "categories": [
            {
              "categoryId": "9355",
              "name": "Cell Phones & Smartphones",
              "group": "Cell Phones & Accessories",
              "leaf": true
            }
          ],
          "credits_charged": 1
        }
      }
    }
  }
}