{"openapi":"3.0.3","info":{"title":"DayBlink Select Partner API","version":"1.0.0","description":"Read-only **live vendor catalog** for partner integrations (Purchase Plus and later partners). Call it from **your website server** — not from a hotelier browser session, and not from the Select marketplace UI.\n\n## Integrate from your server\n\n1. Sign in to Select as a Partner, complete email MFA, and generate an API token (`fp_live_...`).\n2. Store `SELECT_API_TOKEN` on your **server**. Do not put it in frontend JavaScript or mobile apps.\n3. Send `Authorization: Bearer {SELECT_API_TOKEN}` on every catalog `GET /v1`.\n4. On `429`, wait `Retry-After` seconds.\n\nSandbox uses the same paths under `/sandbox/v1` with the published token on `/sandbox`.\n\nDeprecated: `POST /v1/auth/token` with email and password still issues a short-lived JWT. New integrations must use a hashed Partner API token from Select API Access.\n\nYou do **not** need a Supabase URL, anon key, service role key, cookies, or MFA.\n\nBrowser calls only work if we add your origin to `PARTNER_CORS_ORIGINS`. The default is server-to-server (no `Access-Control-Allow-Origin: *`).\n\n## Contract\n\n- Paths use **UUID** `id` values, never slugs. Use `slug` only for your own URLs.\n- Lists: `page` (default 1), `perPage` (default 50, max 100). Body: `{ items, page, perPage, total }`.\n- Only **live** listings are returned. Draft / pending vendors are `404 not_found`.\n- Unknown JSON fields may appear in later additive releases — ignore them.\n- Quote `x-request-id` in support tickets.\n\n## Calling the API\n\n1. In Select, open **API Access** and generate a token (`fp_live_...`). The raw value is shown once — store it on your server.\n2. Send `Authorization: Bearer {token}` on every catalog `GET /v1`.\n3. Import `/openapi.json` into Postman, Insomnia, or your codegen if you want a machine-readable contract.\n4. Practice against `/sandbox/v1` with the published sandbox token (same path suffixes).\n\n`POST /v1/auth/token` is deprecated. Do not use it for new integrations.\n\n## Out of scope (v1)\n\nInquiries, hotels, invites, draft listings, user accounts, Brandfetch, and admin mutations.","contact":{"name":"DayBlink Select Partner API","url":"https://api.dayblinkselect.com"}},"externalDocs":{"description":"Short how-to (same host)","url":"/doc"},"servers":[{"url":"https://api.dayblinkselect.com","description":"This host"},{"url":"https://dayblinkselect-api-service-git-main-day-blink-gpo.vercel.app","description":"Production"}],"tags":[{"name":"Authentication","description":"Catalog calls use a Select-issued `fp_live_...` Bearer token. `POST /v1/auth/token` is deprecated. Sandbox uses `/sandbox/v1` with the published `fp_test_` token."},{"name":"Catalog","description":"Live vendors and taxonomy for filters."},{"name":"Rankings","description":"Full scores for live vendors (not the public #1-only teaser)."}],"security":[{"PartnerBearer":[]}],"paths":{"/v1/auth/token":{"post":{"tags":["Authentication"],"operationId":"createAccessToken","deprecated":true,"summary":"[Deprecated] Mint or refresh a JWT","description":"**Deprecated.** New partners must use a Select API Access token (`fp_live_...`) as Bearer on catalog routes. This password/refresh grant still issues a short-lived JWT for existing consumers. Select email and password are for human login only — do not put them on your server. Body must be JSON and at most 4KB. Rate limit: **10 requests / minute** per IP and per email.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/PasswordGrantRequest"},{"$ref":"#/components/schemas/RefreshGrantRequest"}]},"examples":{"password":{"summary":"Password grant","value":{"email":"partner@example.com","password":"your-password"}},"refresh":{"summary":"Refresh token grant","value":{"grant_type":"refresh_token","refresh_token":"refresh-token-from-previous-grant"}}}}}},"responses":{"200":{"description":"Tokens issued. Use `access_token` as a Bearer credential.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenGrant"},"example":{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","refresh_token":"refresh-token-value","expires_in":3600,"token_type":"bearer"}}}},"400":{"description":"Request body larger than 4KB.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"unauthorized","message":"Missing or invalid access token."}}}}},"401":{"description":"Missing fields, invalid JSON, bad credentials, unknown refresh token, or account is not an active partner.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"unauthorized","message":"Missing or invalid access token."}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/taxonomy":{"get":{"tags":["Catalog"],"operationId":"getTaxonomy","summary":"List taxonomy used as vendor filters","description":"Categories, subcategories, spend areas, and enabled regions. Use the `id` values as `category_id`, `subcategory_id`, `spend_area_id`, and `region_id` on `GET /v1/vendors`.","responses":{"200":{"description":"Taxonomy snapshot.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Taxonomy"},"example":{"categories":[{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","name":"Housekeeping","slug":"housekeeping"}],"subcategories":[{"id":"b2c3d4e5-f6a7-8901-bcde-f12345678901","name":"Linen","slug":"linen","category_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"spend_areas":[{"id":"c3d4e5f6-a7b8-9012-cdef-123456789012","name":"Guestroom supplies"}],"regions":[{"id":"d4e5f6a7-b8c9-0123-def0-234567890123","name":"United States"}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/vendors":{"get":{"tags":["Catalog"],"operationId":"listVendors","summary":"List live vendors","description":"Paginated live listings. List items omit `email` and long-form HTML — use `GET /v1/vendors/{id}` for those fields. Combine filters; results are live vendors only.","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"},{"name":"q","in":"query","required":false,"description":"Search name and listing text. Special characters are stripped; max 200 characters.","schema":{"type":"string","maxLength":200},"example":"linen"},{"name":"vendor_id","in":"query","required":false,"description":"Return at most this live vendor.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"20257f50-0aff-4499-8977-5d5abd56f664"},{"name":"category_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"subcategory_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"b2c3d4e5-f6a7-8901-bcde-f12345678901"},{"name":"region_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"d4e5f6a7-b8c9-0123-def0-234567890123"},{"name":"spend_area_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"c3d4e5f6-a7b8-9012-cdef-123456789012"},{"name":"country","in":"query","required":false,"description":"Country code as stored on the listing, for example `US`.","schema":{"type":"string","example":"US"}}],"responses":{"200":{"description":"A page of live vendors.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorListPage"},"example":{"items":[{"id":"20257f50-0aff-4499-8977-5d5abd56f664","slug":"acme-linen","name":"Acme Linen","logo_url":"https://cdn.example.com/logos/acme-linen.png","short_description":"Hospitality linen and laundry programs.","website_url":"https://acmelinen.example","city":"Dallas","state":"TX","country":"US","p_plus_id":null,"categories":[{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","name":"Housekeeping","slug":"housekeeping"}]}],"page":1,"perPage":2,"total":140}}}},"400":{"$ref":"#/components/responses/InvalidId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/vendors/{id}":{"get":{"tags":["Catalog"],"operationId":"getVendor","summary":"Get one live vendor","description":"Full listing including `email` and `full_description`. `{id}` must be a UUID. Unknown or not-live vendors return `404`.","parameters":[{"$ref":"#/components/parameters/VendorIdPath"}],"responses":{"200":{"description":"Live vendor detail.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorDetail"},"example":{"id":"20257f50-0aff-4499-8977-5d5abd56f664","slug":"acme-linen","name":"Acme Linen","logo_url":"https://cdn.example.com/logos/acme-linen.png","short_description":"Hospitality linen and laundry programs.","website_url":"https://acmelinen.example","city":"Dallas","state":"TX","country":"US","p_plus_id":null,"categories":[{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","name":"Housekeeping","slug":"housekeeping"}],"full_description":"<p>Full listing copy…</p>","email":"sales@acmelinen.example","company_size":"201-500","gpo_discount_label":"Preferred terms","subcategories":[{"id":"b2c3d4e5-f6a7-8901-bcde-f12345678901","name":"Linen","slug":"linen","category_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"}]}}}},"400":{"$ref":"#/components/responses/InvalidId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/vendors/{id}/ranking":{"get":{"tags":["Rankings"],"operationId":"getVendorRanking","summary":"Get one live vendor's global ranking","description":"Full score breakdown plus global `rank_number`. Vendor must be live.","parameters":[{"$ref":"#/components/parameters/VendorIdPath"}],"responses":{"200":{"description":"Global ranking row for that vendor.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorRanking"},"example":{"vendor_id":"20257f50-0aff-4499-8977-5d5abd56f664","rank_number":12,"master_score":81,"customer_satisfaction_score":80,"market_authority_score":78,"scale_stability_score":82,"global_reach_score":79,"is_partner":true}}}},"400":{"$ref":"#/components/responses/InvalidId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/rankings":{"get":{"tags":["Rankings"],"operationId":"listRankings","summary":"List global rankings","description":"Live vendors only, ordered by `rank_number` ascending. Optional `vendor_id` returns that row only.","parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"},{"name":"vendor_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"20257f50-0aff-4499-8977-5d5abd56f664"}],"responses":{"200":{"description":"A page of global ranking rows (full scores).","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorRankingPage"},"example":{"items":[{"vendor_id":"20257f50-0aff-4499-8977-5d5abd56f664","rank_number":12,"master_score":81,"customer_satisfaction_score":80,"market_authority_score":78,"scale_stability_score":82,"global_reach_score":79,"is_partner":true}],"page":1,"perPage":50,"total":140}}}},"400":{"$ref":"#/components/responses/InvalidId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/categories/{id}/rankings":{"get":{"tags":["Rankings"],"operationId":"listCategoryRankings","summary":"List rankings for a category","description":"`{id}` is the category UUID from `GET /v1/taxonomy`. Items include `vendor_id`, `rank_number`, `master_score`, and `is_partner` (not the full score breakdown).","parameters":[{"$ref":"#/components/parameters/CategoryIdPath"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"}],"responses":{"200":{"description":"Category rank page.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryRankingPage"},"example":{"category_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","items":[{"vendor_id":"3c4d5e6f-7890-12ab-cdef-345678901234","rank_number":1,"master_score":88,"is_partner":true},{"vendor_id":"20257f50-0aff-4499-8977-5d5abd56f664","rank_number":2,"master_score":81,"is_partner":true}],"page":1,"perPage":2,"total":48}}}},"400":{"$ref":"#/components/responses/InvalidId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Unknown category UUID.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"not_found","message":"Category not found."}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/subcategories/{id}/rankings":{"get":{"tags":["Rankings"],"operationId":"listSubcategoryRankings","summary":"List rankings for a subcategory","description":"Same shape as category rankings, with `subcategory_id`. Lists may be shorter (top vendors per subcategory).","parameters":[{"$ref":"#/components/parameters/SubcategoryIdPath"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"}],"responses":{"200":{"description":"Subcategory rank page.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubcategoryRankingPage"},"example":{"subcategory_id":"b2c3d4e5-f6a7-8901-bcde-f12345678901","items":[{"vendor_id":"20257f50-0aff-4499-8977-5d5abd56f664","rank_number":2,"master_score":81,"is_partner":true}],"page":1,"perPage":50,"total":12}}}},"400":{"$ref":"#/components/responses/InvalidId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Unknown subcategory UUID.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"not_found","message":"Subcategory not found."}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}},"components":{"securitySchemes":{"PartnerBearer":{"type":"http","scheme":"bearer","bearerFormat":"fp_live_ token or JWT","description":"Select Partner API token (`fp_live_...`) from **API Access**. Send as `Authorization: Bearer {token}`. Select cookies and MFA cannot substitute. A deprecated JWT from `POST /v1/auth/token` is still accepted for existing consumers."}},"headers":{"RequestId":{"description":"Correlation id. Send this when you contact support.","schema":{"type":"string","format":"uuid"}},"RateLimitRemaining":{"description":"Catalog calls remaining in the current minute for this partner.","schema":{"type":"integer","minimum":0}},"RetryAfter":{"description":"Seconds to wait before retrying a `429`.","schema":{"type":"integer","minimum":1}}},"parameters":{"Page":{"name":"page","in":"query","required":false,"description":"1-based page. Invalid values fall back to `1`.","schema":{"type":"integer","minimum":1,"default":1}},"PerPage":{"name":"perPage","in":"query","required":false,"description":"Page size. Clamped to 1–100. Default 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"VendorIdPath":{"name":"id","in":"path","required":true,"description":"Vendor UUID (`id`), not slug.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"20257f50-0aff-4499-8977-5d5abd56f664"},"CategoryIdPath":{"name":"id","in":"path","required":true,"description":"Category UUID from `GET /v1/taxonomy`.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"SubcategoryIdPath":{"name":"id","in":"path","required":true,"description":"Subcategory UUID from `GET /v1/taxonomy`.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"example":"b2c3d4e5-f6a7-8901-bcde-f12345678901"}},"schemas":{"PasswordGrantRequest":{"type":"object","title":"Password grant","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"partner@example.com"},"password":{"type":"string","format":"password","minLength":1},"grant_type":{"type":"string","enum":["password"],"default":"password"}}},"RefreshGrantRequest":{"type":"object","title":"Refresh token grant","required":["grant_type","refresh_token"],"properties":{"grant_type":{"type":"string","enum":["refresh_token"]},"refresh_token":{"type":"string","minLength":1}}},"TokenGrant":{"type":"object","required":["access_token","refresh_token","expires_in","token_type"],"properties":{"access_token":{"type":"string","description":"JWT. Send as Bearer on catalog routes."},"refresh_token":{"type":"string"},"expires_in":{"type":"integer","description":"Seconds until `access_token` expires. Typically 3600.","example":3600},"token_type":{"type":"string","enum":["bearer"]}}},"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["invalid_id","unauthorized","token_expired","forbidden","not_found","rate_limit_exceeded","internal_error"]},"message":{"type":"string"}}}}},"Category":{"type":"object","required":["id","name","slug"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"slug":{"type":"string"}}},"Subcategory":{"type":"object","required":["id","name","slug","category_id"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"name":{"type":"string"},"slug":{"type":"string"},"category_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"}}},"NamedId":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"name":{"type":"string"}}},"Taxonomy":{"type":"object","required":["categories","subcategories","spend_areas","regions"],"properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"subcategories":{"type":"array","items":{"$ref":"#/components/schemas/Subcategory"}},"spend_areas":{"type":"array","items":{"$ref":"#/components/schemas/NamedId"}},"regions":{"type":"array","items":{"$ref":"#/components/schemas/NamedId"}}}},"VendorListItem":{"type":"object","required":["id","slug","name","logo_url","short_description","website_url","city","state","country","p_plus_id","categories"],"properties":{"id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"slug":{"type":"string","nullable":true},"name":{"type":"string"},"logo_url":{"type":"string","nullable":true,"format":"uri"},"short_description":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true,"format":"uri"},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"p_plus_id":{"type":"string","nullable":true},"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}}},"VendorDetail":{"allOf":[{"$ref":"#/components/schemas/VendorListItem"},{"type":"object","required":["full_description","email","company_size","gpo_discount_label","subcategories"],"properties":{"full_description":{"type":"string","nullable":true,"description":"May contain HTML from the listing."},"email":{"type":"string","format":"email","nullable":true},"company_size":{"type":"string","nullable":true},"gpo_discount_label":{"type":"string","nullable":true},"subcategories":{"type":"array","items":{"$ref":"#/components/schemas/Subcategory"}}}}]},"VendorListPage":{"type":"object","required":["items","page","perPage","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/VendorListItem"}},"page":{"type":"integer","minimum":1},"perPage":{"type":"integer","minimum":1,"maximum":100},"total":{"type":"integer","minimum":0}}},"VendorRanking":{"type":"object","required":["vendor_id","rank_number","master_score","customer_satisfaction_score","market_authority_score","scale_stability_score","global_reach_score","is_partner"],"properties":{"vendor_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"rank_number":{"type":"integer","minimum":1},"master_score":{"type":"number"},"customer_satisfaction_score":{"type":"number"},"market_authority_score":{"type":"number"},"scale_stability_score":{"type":"number"},"global_reach_score":{"type":"number"},"is_partner":{"type":"boolean"}}},"VendorRankingPage":{"type":"object","required":["items","page","perPage","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/VendorRanking"}},"page":{"type":"integer","minimum":1},"perPage":{"type":"integer","minimum":1,"maximum":100},"total":{"type":"integer","minimum":0}}},"ScopedRankingItem":{"type":"object","required":["vendor_id","rank_number","master_score","is_partner"],"properties":{"vendor_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"rank_number":{"type":"integer","minimum":1},"master_score":{"type":"number"},"is_partner":{"type":"boolean"}}},"CategoryRankingPage":{"type":"object","required":["category_id","items","page","perPage","total"],"properties":{"category_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ScopedRankingItem"}},"page":{"type":"integer","minimum":1},"perPage":{"type":"integer","minimum":1,"maximum":100},"total":{"type":"integer","minimum":0}}},"SubcategoryRankingPage":{"type":"object","required":["subcategory_id","items","page","perPage","total"],"properties":{"subcategory_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ScopedRankingItem"}},"page":{"type":"integer","minimum":1},"perPage":{"type":"integer","minimum":1,"maximum":100},"total":{"type":"integer","minimum":0}}}},"responses":{"InvalidId":{"description":"Path or query value is not a UUID. `error.message` names the field.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"invalid_id","message":"vendor_id must be a UUID."}}}}},"Unauthorized":{"description":"Missing, malformed, revoked, invalid, or expired Bearer token.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unauthorized":{"summary":"Missing or invalid token","value":{"error":{"code":"unauthorized","message":"Missing or invalid access token."}}},"token_expired":{"summary":"Expired Select token or deprecated JWT","value":{"error":{"code":"token_expired","message":"Access token expired. Refresh and retry."}}}}}}},"Forbidden":{"description":"Token is valid but the user is not an active partner.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"forbidden","message":"This account cannot access the partner API."}}}}},"NotFound":{"description":"Unknown UUID, or the vendor exists but is not live.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"not_found","message":"Vendor not found."}}}}},"RateLimited":{"description":"Catalog: more than 60 requests per minute per partner (and per IP). Token door: more than 10 per minute. Wait `Retry-After` seconds.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"x-ratelimit-remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"rate_limit_exceeded","message":"Too many requests."}}}}},"InternalError":{"description":"Unexpected failure. Retry once, then contact support with `x-request-id`.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"internal_error","message":"Something went wrong."}}}}},"ServiceUnavailable":{"description":"Rate limiter unavailable while enforcement is required. Retry later.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"internal_error","message":"Something went wrong."}}}}}}}}