{"openapi":"3.1.0","paths":{"/v1/notices/search":{"get":{"description":"Search and filter procurement notices. Every parameter is optional, so filters can stand alone without a keyword. Results are ranked by relevance unless `sort` is set, and paginated with `next_cursor`.","operationId":"searchNotices","parameters":[{"name":"query","required":false,"in":"query","description":"Free-text keyword search over the notice (each 2–500 characters). Repeatable; multiple values are combined per `query_operator`.","schema":{"maxItems":50,"type":"array","items":{"type":"string","minLength":2,"maxLength":500}},"style":"form","explode":true},{"name":"query_operator","required":false,"in":"query","description":"How multiple `query` keywords combine: match all (`and`) or any (`or`). Default `or`.","schema":{"default":"or","type":"string","enum":["and","or"]}},{"name":"country_code","required":false,"in":"query","description":"Filter to notices in these ISO 3166-1 alpha-2 countries. Repeatable.","schema":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"style":"form","explode":true},{"name":"cpv_code","required":false,"in":"query","description":"Filter to notices classified under these CPV codes. Repeatable.","schema":{"maxItems":100,"type":"array","items":{"type":"string","minLength":1}},"style":"form","explode":true},{"name":"buyer_id","required":false,"in":"query","description":"Filter to notices involving these buyers (by id). Repeatable.","schema":{"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}},"style":"form","explode":true},{"name":"supplier_id","required":false,"in":"query","description":"Filter to notices awarded to these suppliers (by id). Repeatable.","schema":{"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}},"style":"form","explode":true},{"name":"stage","required":false,"in":"query","description":"Filter to notices in these stages. Repeatable.","schema":{"maxItems":10,"type":"array","items":{"type":"string","enum":["pipeline","pre_tender","stale_pre_tender","open_tender","closed_tender","canceled_tender","unknown_tender","awarded_contract","expired_contract","canceled_award"],"description":"The notice's procurement stage.","x-enumDescriptions":{"pipeline":"An early signal that a procurement is coming — spotted in a buyer's forward plan or contract pipeline, before any formal notice. No tender documents exist yet.","pre_tender":"The buyer has published a formal early-market notice (e.g. a planning or prior-information notice). The tender is not open yet.","stale_pre_tender":"A pre-tender notice that has aged well past the point where a tender would normally have followed. Treat it as unlikely to progress.","open_tender":"Accepting bids — the submission deadline (`close_date`) has not passed.","closed_tender":"The submission deadline has passed and the buyer has not published an award yet.","canceled_tender":"The buyer withdrew or abandoned the procurement before awarding it.","unknown_tender":"A tender notice whose deadline could not be determined from the source, so we can't say whether it is still open.","awarded_contract":"A contract has been awarded. See `contracts` for the suppliers and awarded values.","expired_contract":"The awarded contract has passed the end of its known term. Note that this is derived from the contract record, so an `expired_contract` can still carry a **future** `expiry_date` — don't infer timing from the stage.","canceled_award":"An award that was later cancelled or annulled."}}},"style":"form","explode":true},{"name":"framework_id","required":false,"in":"query","description":"Filter to notices related to these frameworks (by id) — a framework agreement or a call-off against it. Repeatable.","schema":{"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}},"style":"form","explode":true},{"name":"framework_activity","required":false,"in":"query","description":"Narrow by framework relationship (agreement vs call-off).","schema":{"type":"string","enum":["only_framework_agreements","only_call_offs","exclude_framework_agreements","exclude_all"],"x-enumDescriptions":{"only_framework_agreements":"Only notices that establish a framework agreement, excluding the call-offs made under one.","only_call_offs":"Only notices that are call-offs (individual awards) under an existing framework.","exclude_framework_agreements":"Everything except the notices that establish a framework — keeps call-offs and non-framework procurements.","exclude_all":"Only procurements unrelated to any framework."}}},{"name":"publish_date_gte","required":false,"in":"query","description":"Only notices published on or after this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"publish_date_lte","required":false,"in":"query","description":"Only notices published on or before this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"close_date_gte","required":false,"in":"query","description":"Only notices whose tender close date is on or after this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"close_date_lte","required":false,"in":"query","description":"Only notices whose tender close date is on or before this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"expiry_date_gte","required":false,"in":"query","description":"Only notices whose contract expiry date is on or after this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"expiry_date_lte","required":false,"in":"query","description":"Only notices whose contract expiry date is on or before this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"award_date_gte","required":false,"in":"query","description":"Only notices whose award date is on or after this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"award_date_lte","required":false,"in":"query","description":"Only notices whose award date is on or before this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"value_gte","required":false,"in":"query","description":"Only notices whose estimated value is greater than or equal to this amount, in the notice's own currency (values are not currency-normalized). Excludes notices with no value.","schema":{"minimum":1,"type":"number"}},{"name":"value_lte","required":false,"in":"query","description":"Only notices whose estimated value is less than or equal to this amount, in the notice's own currency (values are not currency-normalized). Excludes notices with no value.","schema":{"minimum":1,"type":"number"}},{"name":"sort","required":false,"in":"query","description":"Sort field. Omitted = relevance ranking. For date sorts (close/award/expiry, often null), notices missing that date sort last in both directions.","schema":{"type":"string","enum":["publish_date","close_date","award_date","expiry_date","value"]}},{"name":"order","required":false,"in":"query","description":"Sort direction (default desc). Applies when `sort` is set.","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"limit","required":false,"in":"query","description":"Maximum results per page (1–50, default 20). Ignored when `cursor` is set.","schema":{"minimum":1,"maximum":50,"default":20,"type":"integer"}},{"name":"cursor","required":false,"in":"query","description":"Opaque pagination cursor from a previous response's `next_cursor`. Carries the page and page size, so `limit` is ignored when it is present.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of matching notices.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoticeSearchResponseDto"},"example":{"items":[{"id":"8f14e45f-ea0d-4a3b-9c2e-1d7b6a5c4e30","title":"Managed Cyber Security Operations Centre (SOC) Services","description":"The Authority is seeking a supplier to deliver a managed Security Operations Centre, including 24/7 monitoring, threat intelligence and incident response, for an initial term of three years with an optional two-year extension.","country_code":"GB","stage":"open_tender","source_url":"https://www.find-tender.service.gov.uk/Notice/012345-2026","publish_date":"2026-07-14","close_date":"2026-08-29","award_date":null,"expiry_date":null,"value":{"amount":4500000,"currency":"GBP"},"buyers":[{"id":"3c6e0b8a-9c15-4f2d-8b7a-2e5d1c9f4a60","name":"Department for Work and Pensions"}],"cpv_codes":[{"code":"72500000","name":"Computer-related services"},{"code":"79710000","name":"Security services"}],"framework":null,"lots":[{"id":"1","title":"Lot 1 — Monitoring and detection","description":"24/7 SOC monitoring, alert triage and detection engineering.","value":{"amount":3000000,"currency":"GBP"},"cpv_codes":[{"code":"72500000","name":"Computer-related services"}],"contract_period":{"start_date":"2026-11-01","end_date":"2029-10-31","max_extent_date":"2031-10-31"}},{"id":"2","title":"Lot 2 — Incident response retainer","description":"On-call incident response and forensic investigation.","value":{"amount":1500000,"currency":"GBP"},"cpv_codes":[{"code":"79710000","name":"Security services"}],"contract_period":{"start_date":"2026-11-01","end_date":"2029-10-31","max_extent_date":null}}],"contracts":[]}],"next_cursor":"eyJwYWdlIjoyLCJsaW1pdCI6MjB9"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Search notices by keyword","tags":["Notices"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl -G https://api.stotles.com/v1/notices/search \\\n  -H \"x-api-key: $STOTLES_API_KEY\" \\\n  --data-urlencode \"query=cyber security\" \\\n  -d \"stage=open_tender\" \\\n  -d \"country_code=GB\" \\\n  -d \"limit=20\""}]}},"/v1/notices/{id}":{"get":{"description":"Fetch a single notice, including its lots and any awarded contracts. The `id` is the same identifier returned by notice search and by the `buyer_id`/`supplier_id` filters.","operationId":"getNotice","parameters":[{"name":"id","required":true,"in":"path","description":"The notice's unique identifier.","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"The notice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoticeResponseDto"},"example":{"id":"8f14e45f-ea0d-4a3b-9c2e-1d7b6a5c4e30","title":"Managed Cyber Security Operations Centre (SOC) Services","description":"The Authority is seeking a supplier to deliver a managed Security Operations Centre, including 24/7 monitoring, threat intelligence and incident response, for an initial term of three years with an optional two-year extension.","country_code":"GB","stage":"open_tender","source_url":"https://www.find-tender.service.gov.uk/Notice/012345-2026","publish_date":"2026-07-14","close_date":"2026-08-29","award_date":null,"expiry_date":null,"value":{"amount":4500000,"currency":"GBP"},"buyers":[{"id":"3c6e0b8a-9c15-4f2d-8b7a-2e5d1c9f4a60","name":"Department for Work and Pensions"}],"cpv_codes":[{"code":"72500000","name":"Computer-related services"},{"code":"79710000","name":"Security services"}],"framework":null,"lots":[{"id":"1","title":"Lot 1 — Monitoring and detection","description":"24/7 SOC monitoring, alert triage and detection engineering.","value":{"amount":3000000,"currency":"GBP"},"cpv_codes":[{"code":"72500000","name":"Computer-related services"}],"contract_period":{"start_date":"2026-11-01","end_date":"2029-10-31","max_extent_date":"2031-10-31"}},{"id":"2","title":"Lot 2 — Incident response retainer","description":"On-call incident response and forensic investigation.","value":{"amount":1500000,"currency":"GBP"},"cpv_codes":[{"code":"79710000","name":"Security services"}],"contract_period":{"start_date":"2026-11-01","end_date":"2029-10-31","max_extent_date":null}}],"contracts":[]}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Get a notice by id","tags":["Notices"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl https://api.stotles.com/v1/notices/8f14e45f-ea0d-4a3b-9c2e-1d7b6a5c4e30 \\\n  -H \"x-api-key: $STOTLES_API_KEY\""}]}},"/v1/buyers/search":{"get":{"description":"Find public sector buyers by name, optionally narrowed by country or by where they sit in the buyer-type taxonomy. Each result is the full buyer profile — the same shape as `GET /v1/buyers/{id}`.","operationId":"searchBuyers","parameters":[{"name":"query","required":true,"in":"query","description":"Free-text search over the buyer name (2–200 characters).","schema":{"minLength":2,"maxLength":200,"type":"string"}},{"name":"country_code","required":false,"in":"query","description":"Filter to buyers in these ISO 3166-1 alpha-2 countries. Repeatable.","schema":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"style":"form","explode":true},{"name":"type","required":false,"in":"query","description":"Filter to buyers of these types. Repeatable.","schema":{"maxItems":23,"type":"array","items":{"type":"string","enum":["ministerial_department","non_ministerial_department","agencies_and_non_departmental_bodies","other_central","devolved_department","local_authority","purchasing_organization","parish_council","other_local_organization","central_healthcare_organizations","nhs_trusts","nhs_ccg_stp_ics","other_healthcare","police","fire","ambulance","other_blue_light","schools","higher_and_further_education","other_education","housing_associations","other_public_sector","utilities"]}},"style":"form","explode":true},{"name":"type_group","required":false,"in":"query","description":"Filter to buyers in these type groups — matches any type within a group. Repeatable.","schema":{"maxItems":6,"type":"array","items":{"type":"string","enum":["central","local","healthcare","blue_light","education","other"]}},"style":"form","explode":true},{"name":"limit","required":false,"in":"query","description":"Maximum results per page (1–50, default 20). Ignored when `cursor` is set.","schema":{"minimum":1,"maximum":50,"default":20,"type":"integer"}},{"name":"cursor","required":false,"in":"query","description":"Opaque pagination cursor from a previous response's `next_cursor`. Carries the page and page size, so `limit` is ignored when it is present.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of matching buyers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuyerSearchResponseDto"},"example":{"items":[{"id":"3c6e0b8a-9c15-4f2d-8b7a-2e5d1c9f4a60","name":"Department for Work and Pensions","location":{"country_code":"GB","locality":"London"},"employee_count_band":"20000+","website_url":"https://www.gov.uk/government/organisations/department-for-work-pensions","types":[{"id":"ministerial_department","name":"Ministerial department","group":{"id":"central","name":"Central government"}}]},{"id":"5a1f2c7d-4b8e-4c1a-9f3d-6e2b8a4c7d19","name":"Leeds City Council","location":{"country_code":"GB","locality":"Leeds"},"employee_count_band":"10000-19999","website_url":"https://www.leeds.gov.uk","types":[{"id":"local_authority","name":"Local authority","group":{"id":"local","name":"Local government"}}]}],"next_cursor":"eyJwYWdlIjoyLCJsaW1pdCI6MjB9"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Search buyers by name","tags":["Buyers"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl -G https://api.stotles.com/v1/buyers/search \\\n  -H \"x-api-key: $STOTLES_API_KEY\" \\\n  --data-urlencode \"query=city council\" \\\n  -d \"type_group=local\" \\\n  -d \"country_code=GB\""}]}},"/v1/buyers/{id}":{"get":{"description":"Fetch a single buyer, including its location and what kind of public sector body it is. Use the `id` as the `buyer_id` filter on notice search to see what it has been procuring.","operationId":"getBuyer","parameters":[{"name":"id","required":true,"in":"path","description":"The buyer's unique identifier.","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"The buyer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuyerResponseDto"},"example":{"id":"3c6e0b8a-9c15-4f2d-8b7a-2e5d1c9f4a60","name":"Department for Work and Pensions","location":{"country_code":"GB","locality":"London"},"employee_count_band":"20000+","website_url":"https://www.gov.uk/government/organisations/department-for-work-pensions","types":[{"id":"ministerial_department","name":"Ministerial department","group":{"id":"central","name":"Central government"}}]}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Get a buyer by id","tags":["Buyers"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl https://api.stotles.com/v1/buyers/3c6e0b8a-9c15-4f2d-8b7a-2e5d1c9f4a60 \\\n  -H \"x-api-key: $STOTLES_API_KEY\""}]}},"/v1/suppliers/search":{"get":{"description":"Find suppliers that bid for or win public sector contracts, ranked by relevance to the query. `award_count` reflects the awards we have indexed for the supplier.","operationId":"searchSuppliers","parameters":[{"name":"query","required":true,"in":"query","description":"Free-text search over the supplier name (2–200 characters).","schema":{"minLength":2,"maxLength":200,"type":"string"}},{"name":"country_code","required":false,"in":"query","description":"Filter to suppliers in these ISO 3166-1 alpha-2 countries. Repeatable.","schema":{"maxItems":100,"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"}},"style":"form","explode":true},{"name":"limit","required":false,"in":"query","description":"Maximum results per page (1–50, default 20). Ignored when `cursor` is set.","schema":{"minimum":1,"maximum":50,"default":20,"type":"integer"}},{"name":"cursor","required":false,"in":"query","description":"Opaque pagination cursor from a previous response's `next_cursor`. Carries the page and page size, so `limit` is ignored when it is present.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of matching suppliers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierSearchResponseDto"},"example":{"items":[{"id":"b2d4f6a8-1c3e-4d5f-8a9b-0c1d2e3f4a5b","name":"Northbridge Digital Services Ltd","location":{"country_code":"GB"},"award_count":37},{"id":"c3e5a7b9-2d4f-4e6a-9b0c-1d2e3f4a5b6c","name":"Northbridge Consulting Group Ltd","location":{"country_code":"GB"},"award_count":4}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Search suppliers by name","tags":["Suppliers"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl -G https://api.stotles.com/v1/suppliers/search \\\n  -H \"x-api-key: $STOTLES_API_KEY\" \\\n  --data-urlencode \"query=northbridge digital\""}]}},"/v1/suppliers/{id}":{"get":{"description":"Fetch a single supplier. Use the `id` as the `supplier_id` filter on notice search to see the contracts it has been awarded.","operationId":"getSupplier","parameters":[{"name":"id","required":true,"in":"path","description":"The supplier's unique identifier.","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"The supplier.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierDto"},"example":{"id":"b2d4f6a8-1c3e-4d5f-8a9b-0c1d2e3f4a5b","name":"Northbridge Digital Services Ltd","location":{"country_code":"GB"},"award_count":37}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Get a supplier by id","tags":["Suppliers"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl https://api.stotles.com/v1/suppliers/b2d4f6a8-1c3e-4d5f-8a9b-0c1d2e3f4a5b \\\n  -H \"x-api-key: $STOTLES_API_KEY\""}]}},"/v1/frameworks/search":{"get":{"description":"Search and filter framework agreements and dynamic purchasing systems. Every parameter is optional. Use a framework's `id` as the `framework_id` filter on notice search to find the call-offs made under it.","operationId":"searchFrameworks","parameters":[{"name":"query","required":false,"in":"query","description":"Free-text search over the framework name (2–500 characters).","schema":{"minLength":2,"maxLength":500,"type":"string"}},{"name":"stage","required":false,"in":"query","description":"Filter to frameworks in these procurement stages. Repeatable.","schema":{"maxItems":10,"type":"array","items":{"type":"string","enum":["stale","upcoming","tendering","closed","awarded","live","expired","canceled"],"x-enumDescriptions":{"stale":"Announced, but aged past the point where tendering would normally have started. Treat it as unlikely to progress.","upcoming":"Announced or planned. Suppliers cannot apply yet.","tendering":"Open for suppliers to apply to be appointed to the framework.","closed":"The application deadline has passed; the buyer has not yet announced which suppliers were appointed.","awarded":"Suppliers have been appointed, but the agreement isn't available to buy from yet (typically its start date is in the future).","live":"In force — buyers can run call-offs against it, and appointed suppliers can win work.","expired":"Past its end date. No new call-offs are expected.","canceled":"Withdrawn or abandoned before it came into force."}}},"style":"form","explode":true},{"name":"start_date_gte","required":false,"in":"query","description":"Only frameworks whose contract start date is on or after this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"start_date_lte","required":false,"in":"query","description":"Only frameworks whose contract start date is on or before this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"end_date_gte","required":false,"in":"query","description":"Only frameworks whose contract end date is on or after this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"end_date_lte","required":false,"in":"query","description":"Only frameworks whose contract end date is on or before this date (inclusive).","schema":{"format":"date","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Sort field. Omitted = relevance ranking.","schema":{"type":"string","enum":["title","start_date","end_date","stage","value"]}},{"name":"order","required":false,"in":"query","description":"Sort direction (default desc). Applies when `sort` is set.","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"limit","required":false,"in":"query","description":"Maximum results per page (1–50, default 20). Ignored when `cursor` is set.","schema":{"minimum":1,"maximum":50,"default":20,"type":"integer"}},{"name":"cursor","required":false,"in":"query","description":"Opaque pagination cursor from a previous response's `next_cursor`. Carries the page and page size, so `limit` is ignored when it is present.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of matching framework agreements.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FrameworkSearchResponseDto"},"example":{"items":[{"id":"7d9b1f3a-5c2e-4a8b-9d0f-3e6c1a4b7d92","title":"Technology Products & Associated Services 2","description":"An agreement for the supply of hardware, software and associated services to public sector buyers, divided into lots covering devices, networking and audio-visual equipment.","service_provider":{"id":"e1a3c5b7-9d2f-4b6a-8c0e-5f7a9b1c3d40","name":"Crown Commercial Service"},"stage":"live","procedure_type":"framework","value":{"amount":1200000000,"currency":"GBP"},"start_date":"2025-04-01","end_date":"2029-03-31"}],"next_cursor":"eyJwYWdlIjoyLCJsaW1pdCI6MjB9"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Search frameworks by name, stage and date","tags":["Frameworks"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl -G https://api.stotles.com/v1/frameworks/search \\\n  -H \"x-api-key: $STOTLES_API_KEY\" \\\n  --data-urlencode \"query=technology products\" \\\n  -d \"stage=live\""}]}},"/v1/frameworks/{id}":{"get":{"description":"Fetch a single framework agreement, including its procurement stage and contract period.","operationId":"getFramework","parameters":[{"name":"id","required":true,"in":"path","description":"The framework's unique identifier.","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"The framework agreement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FrameworkResponseDto"},"example":{"id":"7d9b1f3a-5c2e-4a8b-9d0f-3e6c1a4b7d92","title":"Technology Products & Associated Services 2","description":"An agreement for the supply of hardware, software and associated services to public sector buyers, divided into lots covering devices, networking and audio-visual equipment.","service_provider":{"id":"e1a3c5b7-9d2f-4b6a-8c0e-5f7a9b1c3d40","name":"Crown Commercial Service"},"stage":"live","procedure_type":"framework","value":{"amount":1200000000,"currency":"GBP"},"start_date":"2025-04-01","end_date":"2029-03-31"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthenticated"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"summary":"Get a framework by id","tags":["Frameworks"],"x-codeSamples":[{"lang":"cURL","label":"curl","source":"curl https://api.stotles.com/v1/frameworks/7d9b1f3a-5c2e-4a8b-9d0f-3e6c1a4b7d92 \\\n  -H \"x-api-key: $STOTLES_API_KEY\""}]}}},"info":{"title":"Stotles API","description":"The Stotles API gives you programmatic access to UK public sector procurement\ndata — notices, buyers, suppliers and framework agreements — as JSON over HTTPS.\n\n## Base URL\n\nAll endpoints live under a versioned path:\n\n```\nhttps://api.stotles.com/v1\n```\n\n## Authentication\n\nEvery request needs an API key, sent in the `x-api-key` header:\n\n```bash\ncurl -G https://api.stotles.com/v1/notices/search \\\n  -H \"x-api-key: $STOTLES_API_KEY\" \\\n  --data-urlencode \"query=cyber security\"\n```\n\nKeys are issued by Stotles — ask your Customer Success Manager. A key identifies\nyour organization, so treat it as a secret: keep it server-side and out of source\ncontrol.\n\nRequests without a valid key get a `401`.\n\n## Rate limits\n\nLimits apply to **your organization as a whole**, not to each key: every key you hold\ndraws on the same allowance, so issuing more keys doesn't raise it.\n\nYou may make **1,000 requests per hour**, and no more than\n**3 requests per second**. Both apply at once, so a burst of parallel\nrequests can be throttled well inside your hourly allowance.\n\nOver either limit you get a `429` carrying a `Retry-After` header — the number of\nseconds to wait. Honour it and retry; a client that retries immediately will keep\ngetting `429`s. If these limits don't fit your use case, talk to your Customer\nSuccess Manager.\n\n## Pagination\n\nList endpoints (`/search`) return an `items` array plus a top-level\n`next_cursor`:\n\n```json\n{ \"items\": [ … ], \"next_cursor\": \"eyJwYWdlIjoyLCJsaW1pdCI6MjB9\" }\n```\n\nTo read the next page, pass that value back as `?cursor=…`. Keep going until\n`next_cursor` is `null`, which means you have reached the last page.\n\nTwo things to get right:\n\n- **A short page is not the last page.** A page can contain fewer than `limit`\n  items and still have more results behind it. Only `next_cursor: null` ends the\n  loop.\n- **Cursors are opaque.** Pass them back byte-for-byte. Don't decode, construct or\n  persist them — the encoding is an implementation detail and may change.\n\n## Errors\n\nErrors use [RFC 9457 problem details](https://www.rfc-editor.org/rfc/rfc9457) with\nthe `application/problem+json` content type:\n\n```json\n{\n  \"type\": \"https://api.stotles.com/problems/validation\",\n  \"title\": \"Request validation failed\",\n  \"status\": 400,\n  \"detail\": \"The request parameters failed validation. See the 'errors' array for details.\",\n  \"errors\": [{ \"parameter\": \"limit\", \"detail\": \"Too big: expected number to be <=50\" }]\n}\n```\n\n- **Branch on `type`**, not on `title` or `detail` — `type` is a stable\n  identifier per error category; the human-readable fields may be reworded.\n- On validation failures, `errors[]` locates each problem: `parameter` for a\n  query or path parameter, `pointer` for a request body field, `header` for a\n  header.\n\n## Conventions\n\n- **Field names and query parameters are `snake_case`.**\n- **Identifiers are UUIDs.** The `id` a resource returns is the same `id` you\n  filter by (`buyer_id`, `supplier_id`, `framework_id`).\n- **Dates are calendar dates**, `YYYY-MM-DD`, never timestamps. There is no\n  meaningful empty date, so an unknown date is `null`.\n- **Money is a decimal amount plus a currency** — `{ \"amount\": 4500000, \"currency\": \"GBP\" }`\n  — not integer minor units. Amounts can be large and are estimates, so parse them\n  with a big-decimal type rather than a float. `currency` can be `null` when the\n  source didn't state one.\n- **Country codes are ISO 3166-1 alpha-2** (`GB`, `IE`).\n- **Multi-value filters repeat the parameter**: `?stage=open_tender&stage=closed_tender`\n  matches either. Don't comma-join values.\n- **Range filters carry an explicit operator suffix** — `publish_date_gte`,\n  `value_lte`. Both bounds are inclusive.\n- **Unknown optional text is an empty string** where blank is meaningful, and\n  `null` where absence is meaningful. Each field's description says which.\n\n## Versioning and stability\n\nThe version is in the path (`/v1`). Within a version we make only additive\nchanges — new endpoints, new optional parameters, new response fields — so **write\nclients that ignore fields they don't recognize**. Anything breaking (removing or\nrenaming a field, changing a type, tightening validation) goes in a new version,\nand we will contact you before retiring one.\n\n## Support\n\nFor questions, bug reports, or requests for data we don't expose yet, contact your\nStotles Customer Success Manager.","version":"1.0","contact":{"name":"Stotles API Support","url":"https://www.stotles.com"}},"tags":[{"name":"Notices","description":"Public sector procurement notices."},{"name":"Buyers","description":"Public sector buyers and their procurement activity."},{"name":"Suppliers","description":"Suppliers bidding for and winning public sector contracts."},{"name":"Frameworks","description":"Framework agreements and dynamic purchasing systems."}],"servers":[{"url":"https://api.stotles.com","description":"Production"}],"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"x-api-key"}},"schemas":{"NoticeSearchResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The notice's unique identifier."},"title":{"type":"string","description":"The notice's title."},"description":{"type":"string","description":"The notice's description."},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 country code the notice relates to."},"stage":{"type":"string","enum":["pipeline","pre_tender","stale_pre_tender","open_tender","closed_tender","canceled_tender","unknown_tender","awarded_contract","expired_contract","canceled_award"],"description":"The notice's procurement stage.","x-enumDescriptions":{"pipeline":"An early signal that a procurement is coming — spotted in a buyer's forward plan or contract pipeline, before any formal notice. No tender documents exist yet.","pre_tender":"The buyer has published a formal early-market notice (e.g. a planning or prior-information notice). The tender is not open yet.","stale_pre_tender":"A pre-tender notice that has aged well past the point where a tender would normally have followed. Treat it as unlikely to progress.","open_tender":"Accepting bids — the submission deadline (`close_date`) has not passed.","closed_tender":"The submission deadline has passed and the buyer has not published an award yet.","canceled_tender":"The buyer withdrew or abandoned the procurement before awarding it.","unknown_tender":"A tender notice whose deadline could not be determined from the source, so we can't say whether it is still open.","awarded_contract":"A contract has been awarded. See `contracts` for the suppliers and awarded values.","expired_contract":"The awarded contract has passed the end of its known term. Note that this is derived from the contract record, so an `expired_contract` can still carry a **future** `expiry_date` — don't infer timing from the stage.","canceled_award":"An award that was later cancelled or annulled."}},"source_url":{"type":"string","description":"URL of the notice on the original source."},"publish_date":{"type":"string","format":"date","description":"Date this notice was published (its phase's release date)."},"close_date":{"type":["string","null"],"format":"date","description":"Bid submission deadline (tender close). Indicative on pre-tender notices; null on award/contract notices (the deadline is on the sibling tender notice)."},"award_date":{"type":["string","null"],"format":"date","description":"Date the contract was awarded. Best-effort (may fall back to contract start); earliest across awards. Null before award."},"expiry_date":{"type":["string","null"],"format":"date","description":"Earliest expected contract end date. Excludes extensions/options, so it is the earliest — not latest — end. Null when not applicable or unknown."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Estimated total value of the notice; null when no amount is known."},"buyers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The buyer's unique identifier."},"name":{"type":"string","description":"The buyer's name."}},"required":["id","name"]},"description":"Buyers associated with the notice."},"cpv_codes":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"The CPV code."},"name":{"type":"string","description":"Human-readable label for the CPV code."}},"required":["code","name"]},"description":"CPV classification codes for the notice."},"framework":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"The related framework's unique identifier."},"relationship":{"type":"string","enum":["framework_agreement","call_off"],"description":"How this notice relates to the framework: `framework_agreement` = it establishes the framework; `call_off` = it is a call-off under it.","x-enumDescriptions":{"framework_agreement":"This notice establishes the framework.","call_off":"This notice is a call-off (an individual award) made under the framework."}}},"required":["id","relationship"],"description":"The framework this notice relates to; null when it is unrelated to any framework."},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The lot's identifier within the notice."},"title":{"type":"string","description":"The lot's title."},"description":{"type":"string","description":"The lot's description."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Estimated value of the lot; null when no amount is known."},"cpv_codes":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"The CPV code."},"name":{"type":"string","description":"Human-readable label for the CPV code."}},"required":["code","name"]},"description":"CPV classification codes for the lot."},"contract_period":{"type":"object","properties":{"start_date":{"type":["string","null"],"format":"date","description":"Start of the contract period. Null when unknown."},"end_date":{"type":["string","null"],"format":"date","description":"Earliest expected end of the contract period. Null when unknown."},"max_extent_date":{"type":["string","null"],"format":"date","description":"Latest date the period can be extended to (excl. is the earliest end). Null when unknown."}},"required":["start_date","end_date","max_extent_date"],"description":"The lot's contract period."}},"required":["id","title","description","value","cpv_codes","contract_period"]},"description":"Lots the notice is divided into."},"contracts":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"The contract's title."},"description":{"type":"string","description":"The contract's description."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Awarded value of the contract; null when no amount is known."},"award_date":{"type":["string","null"],"format":"date","description":"Date the contract was awarded. Null when unknown."},"contract_period":{"type":"object","properties":{"start_date":{"type":["string","null"],"format":"date","description":"Start of the contract period. Null when unknown."},"end_date":{"type":["string","null"],"format":"date","description":"Earliest expected end of the contract period. Null when unknown."},"max_extent_date":{"type":["string","null"],"format":"date","description":"Latest date the period can be extended to (excl. is the earliest end). Null when unknown."}},"required":["start_date","end_date","max_extent_date"],"description":"The contract's period."},"cpv_codes":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"The CPV code."},"name":{"type":"string","description":"Human-readable label for the CPV code."}},"required":["code","name"]},"description":"CPV classification codes for the contract."},"suppliers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The supplier's unique identifier."},"name":{"type":"string","description":"The supplier's name."}},"required":["id","name"]},"description":"Suppliers awarded the contract (by id)."},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The lot's identifier within the notice."},"title":{"type":"string","description":"The lot's title."}},"required":["id","title"]},"description":"Lots covered by the contract."}},"required":["title","description","value","award_date","contract_period","cpv_codes","suppliers","lots"]},"description":"Contracts/awards made under the notice."}},"required":["id","title","description","country_code","stage","source_url","publish_date","close_date","award_date","expiry_date","value","buyers","cpv_codes","framework","lots","contracts"]},"description":"The matching notices, most relevant first."},"next_cursor":{"type":["string","null"],"description":"Opaque cursor for the next page of results; null when this is the last page."}},"required":["items","next_cursor"]},"NoticeResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The notice's unique identifier."},"title":{"type":"string","description":"The notice's title."},"description":{"type":"string","description":"The notice's description."},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 country code the notice relates to."},"stage":{"type":"string","enum":["pipeline","pre_tender","stale_pre_tender","open_tender","closed_tender","canceled_tender","unknown_tender","awarded_contract","expired_contract","canceled_award"],"description":"The notice's procurement stage.","x-enumDescriptions":{"pipeline":"An early signal that a procurement is coming — spotted in a buyer's forward plan or contract pipeline, before any formal notice. No tender documents exist yet.","pre_tender":"The buyer has published a formal early-market notice (e.g. a planning or prior-information notice). The tender is not open yet.","stale_pre_tender":"A pre-tender notice that has aged well past the point where a tender would normally have followed. Treat it as unlikely to progress.","open_tender":"Accepting bids — the submission deadline (`close_date`) has not passed.","closed_tender":"The submission deadline has passed and the buyer has not published an award yet.","canceled_tender":"The buyer withdrew or abandoned the procurement before awarding it.","unknown_tender":"A tender notice whose deadline could not be determined from the source, so we can't say whether it is still open.","awarded_contract":"A contract has been awarded. See `contracts` for the suppliers and awarded values.","expired_contract":"The awarded contract has passed the end of its known term. Note that this is derived from the contract record, so an `expired_contract` can still carry a **future** `expiry_date` — don't infer timing from the stage.","canceled_award":"An award that was later cancelled or annulled."}},"source_url":{"type":"string","description":"URL of the notice on the original source."},"publish_date":{"type":"string","format":"date","description":"Date this notice was published (its phase's release date)."},"close_date":{"type":["string","null"],"format":"date","description":"Bid submission deadline (tender close). Indicative on pre-tender notices; null on award/contract notices (the deadline is on the sibling tender notice)."},"award_date":{"type":["string","null"],"format":"date","description":"Date the contract was awarded. Best-effort (may fall back to contract start); earliest across awards. Null before award."},"expiry_date":{"type":["string","null"],"format":"date","description":"Earliest expected contract end date. Excludes extensions/options, so it is the earliest — not latest — end. Null when not applicable or unknown."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Estimated total value of the notice; null when no amount is known."},"buyers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The buyer's unique identifier."},"name":{"type":"string","description":"The buyer's name."}},"required":["id","name"]},"description":"Buyers associated with the notice."},"cpv_codes":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"The CPV code."},"name":{"type":"string","description":"Human-readable label for the CPV code."}},"required":["code","name"]},"description":"CPV classification codes for the notice."},"framework":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"The related framework's unique identifier."},"relationship":{"type":"string","enum":["framework_agreement","call_off"],"description":"How this notice relates to the framework: `framework_agreement` = it establishes the framework; `call_off` = it is a call-off under it.","x-enumDescriptions":{"framework_agreement":"This notice establishes the framework.","call_off":"This notice is a call-off (an individual award) made under the framework."}}},"required":["id","relationship"],"description":"The framework this notice relates to; null when it is unrelated to any framework."},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The lot's identifier within the notice."},"title":{"type":"string","description":"The lot's title."},"description":{"type":"string","description":"The lot's description."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Estimated value of the lot; null when no amount is known."},"cpv_codes":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"The CPV code."},"name":{"type":"string","description":"Human-readable label for the CPV code."}},"required":["code","name"]},"description":"CPV classification codes for the lot."},"contract_period":{"type":"object","properties":{"start_date":{"type":["string","null"],"format":"date","description":"Start of the contract period. Null when unknown."},"end_date":{"type":["string","null"],"format":"date","description":"Earliest expected end of the contract period. Null when unknown."},"max_extent_date":{"type":["string","null"],"format":"date","description":"Latest date the period can be extended to (excl. is the earliest end). Null when unknown."}},"required":["start_date","end_date","max_extent_date"],"description":"The lot's contract period."}},"required":["id","title","description","value","cpv_codes","contract_period"]},"description":"Lots the notice is divided into."},"contracts":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"The contract's title."},"description":{"type":"string","description":"The contract's description."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Awarded value of the contract; null when no amount is known."},"award_date":{"type":["string","null"],"format":"date","description":"Date the contract was awarded. Null when unknown."},"contract_period":{"type":"object","properties":{"start_date":{"type":["string","null"],"format":"date","description":"Start of the contract period. Null when unknown."},"end_date":{"type":["string","null"],"format":"date","description":"Earliest expected end of the contract period. Null when unknown."},"max_extent_date":{"type":["string","null"],"format":"date","description":"Latest date the period can be extended to (excl. is the earliest end). Null when unknown."}},"required":["start_date","end_date","max_extent_date"],"description":"The contract's period."},"cpv_codes":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"The CPV code."},"name":{"type":"string","description":"Human-readable label for the CPV code."}},"required":["code","name"]},"description":"CPV classification codes for the contract."},"suppliers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The supplier's unique identifier."},"name":{"type":"string","description":"The supplier's name."}},"required":["id","name"]},"description":"Suppliers awarded the contract (by id)."},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The lot's identifier within the notice."},"title":{"type":"string","description":"The lot's title."}},"required":["id","title"]},"description":"Lots covered by the contract."}},"required":["title","description","value","award_date","contract_period","cpv_codes","suppliers","lots"]},"description":"Contracts/awards made under the notice."}},"required":["id","title","description","country_code","stage","source_url","publish_date","close_date","award_date","expiry_date","value","buyers","cpv_codes","framework","lots","contracts"]},"BuyerSearchResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The buyer's unique identifier."},"name":{"type":"string","description":"The buyer's name."},"location":{"type":"object","properties":{"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 country code; empty string when unknown."},"locality":{"type":["string","null"],"description":"The town or city (e.g. \"London\"); null when unknown."}},"required":["country_code","locality"],"description":"The buyer's location."},"employee_count_band":{"type":["string","null"],"description":"Employee-count band (e.g. \"20000+\"); null when unknown."},"website_url":{"type":["string","null"],"description":"The buyer's website URL; null when unknown."},"types":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["ministerial_department","non_ministerial_department","agencies_and_non_departmental_bodies","other_central","devolved_department","local_authority","purchasing_organization","parish_council","other_local_organization","central_healthcare_organizations","nhs_trusts","nhs_ccg_stp_ics","other_healthcare","police","fire","ambulance","other_blue_light","schools","higher_and_further_education","other_education","housing_associations","other_public_sector","utilities"],"description":"Stable identifier for the buyer type."},"name":{"type":"string","description":"Human-readable label for the buyer type."},"group":{"type":"object","properties":{"id":{"type":"string","enum":["central","local","healthcare","blue_light","education","other"],"description":"Stable identifier for the group."},"name":{"type":"string","description":"Human-readable label for the group."}},"required":["id","name"],"description":"The top-level group this type belongs to."}},"required":["id","name","group"]},"description":"What kind of public sector body this buyer is. Empty when the buyer has no recognized type. Most identifiers read plainly; the one acronym is `nhs_ccg_stp_ics` — NHS Clinical Commissioning Group / Sustainability and Transformation Partnership / Integrated Care System."}},"required":["id","name","location","employee_count_band","website_url","types"]},"description":"The matching buyers, most relevant first."},"next_cursor":{"type":["string","null"],"description":"Opaque cursor for the next page of results; null when this is the last page."}},"required":["items","next_cursor"]},"BuyerResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The buyer's unique identifier."},"name":{"type":"string","description":"The buyer's name."},"location":{"type":"object","properties":{"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 country code; empty string when unknown."},"locality":{"type":["string","null"],"description":"The town or city (e.g. \"London\"); null when unknown."}},"required":["country_code","locality"],"description":"The buyer's location."},"employee_count_band":{"type":["string","null"],"description":"Employee-count band (e.g. \"20000+\"); null when unknown."},"website_url":{"type":["string","null"],"description":"The buyer's website URL; null when unknown."},"types":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["ministerial_department","non_ministerial_department","agencies_and_non_departmental_bodies","other_central","devolved_department","local_authority","purchasing_organization","parish_council","other_local_organization","central_healthcare_organizations","nhs_trusts","nhs_ccg_stp_ics","other_healthcare","police","fire","ambulance","other_blue_light","schools","higher_and_further_education","other_education","housing_associations","other_public_sector","utilities"],"description":"Stable identifier for the buyer type."},"name":{"type":"string","description":"Human-readable label for the buyer type."},"group":{"type":"object","properties":{"id":{"type":"string","enum":["central","local","healthcare","blue_light","education","other"],"description":"Stable identifier for the group."},"name":{"type":"string","description":"Human-readable label for the group."}},"required":["id","name"],"description":"The top-level group this type belongs to."}},"required":["id","name","group"]},"description":"What kind of public sector body this buyer is. Empty when the buyer has no recognized type. Most identifiers read plainly; the one acronym is `nhs_ccg_stp_ics` — NHS Clinical Commissioning Group / Sustainability and Transformation Partnership / Integrated Care System."}},"required":["id","name","location","employee_count_band","website_url","types"]},"SupplierSearchResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The supplier's unique identifier."},"name":{"type":"string","description":"The supplier's name."},"location":{"type":"object","properties":{"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 country code."}},"required":["country_code"],"description":"The supplier's location."},"award_count":{"type":"integer","description":"All-time count of contracts awarded to this supplier."}},"required":["id","name","location","award_count"]},"description":"The matching suppliers, most relevant first."},"next_cursor":{"type":["string","null"],"description":"Opaque cursor for the next page of results; null when this is the last page."}},"required":["items","next_cursor"]},"SupplierDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The supplier's unique identifier."},"name":{"type":"string","description":"The supplier's name."},"location":{"type":"object","properties":{"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 country code."}},"required":["country_code"],"description":"The supplier's location."},"award_count":{"type":"integer","description":"All-time count of contracts awarded to this supplier."}},"required":["id","name","location","award_count"]},"FrameworkSearchResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The framework's unique identifier."},"title":{"type":"string","description":"The framework's title."},"description":{"type":"string","description":"The framework's description; empty when unknown."},"service_provider":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"The provider organisation's unique identifier."},"name":{"type":"string","description":"The provider organisation's name."}},"required":["id","name"],"description":"The framework's service provider organization; null when unknown."},"stage":{"type":"string","enum":["stale","upcoming","tendering","closed","awarded","live","expired","canceled"],"description":"The framework's procurement stage.","x-enumDescriptions":{"stale":"Announced, but aged past the point where tendering would normally have started. Treat it as unlikely to progress.","upcoming":"Announced or planned. Suppliers cannot apply yet.","tendering":"Open for suppliers to apply to be appointed to the framework.","closed":"The application deadline has passed; the buyer has not yet announced which suppliers were appointed.","awarded":"Suppliers have been appointed, but the agreement isn't available to buy from yet (typically its start date is in the future).","live":"In force — buyers can run call-offs against it, and appointed suppliers can win work.","expired":"Past its end date. No new call-offs are expected.","canceled":"Withdrawn or abandoned before it came into force."}},"procedure_type":{"type":["string","null"],"enum":["framework","dynamic_purchasing_system",null],"description":"Whether this is a framework agreement or a dynamic purchasing system; null when unknown."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Estimated total value of the framework; null when no amount is known."},"start_date":{"type":["string","null"],"format":"date","description":"Contract start date (YYYY-MM-DD); null when unknown."},"end_date":{"type":["string","null"],"format":"date","description":"Contract end date (YYYY-MM-DD); null when unknown."}},"required":["id","title","description","service_provider","stage","procedure_type","value","start_date","end_date"]},"description":"The matching frameworks, most relevant first."},"next_cursor":{"type":["string","null"],"description":"Opaque cursor for the next page of results; null when this is the last page."}},"required":["items","next_cursor"]},"FrameworkResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The framework's unique identifier."},"title":{"type":"string","description":"The framework's title."},"description":{"type":"string","description":"The framework's description; empty when unknown."},"service_provider":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"The provider organisation's unique identifier."},"name":{"type":"string","description":"The provider organisation's name."}},"required":["id","name"],"description":"The framework's service provider organization; null when unknown."},"stage":{"type":"string","enum":["stale","upcoming","tendering","closed","awarded","live","expired","canceled"],"description":"The framework's procurement stage.","x-enumDescriptions":{"stale":"Announced, but aged past the point where tendering would normally have started. Treat it as unlikely to progress.","upcoming":"Announced or planned. Suppliers cannot apply yet.","tendering":"Open for suppliers to apply to be appointed to the framework.","closed":"The application deadline has passed; the buyer has not yet announced which suppliers were appointed.","awarded":"Suppliers have been appointed, but the agreement isn't available to buy from yet (typically its start date is in the future).","live":"In force — buyers can run call-offs against it, and appointed suppliers can win work.","expired":"Past its end date. No new call-offs are expected.","canceled":"Withdrawn or abandoned before it came into force."}},"procedure_type":{"type":["string","null"],"enum":["framework","dynamic_purchasing_system",null],"description":"Whether this is a framework agreement or a dynamic purchasing system; null when unknown."},"value":{"type":["object","null"],"properties":{"amount":{"type":"number","description":"The amount as a JSON number, byte-aligned with the upstream feed. Parse with a big-decimal library — do not rely on IEEE-754 float arithmetic."},"currency":{"type":["string","null"],"description":"ISO 4217 currency code (e.g. GBP). Null when the source didn't specify one."}},"required":["amount","currency"],"description":"Estimated total value of the framework; null when no amount is known."},"start_date":{"type":["string","null"],"format":"date","description":"Contract start date (YYYY-MM-DD); null when unknown."},"end_date":{"type":["string","null"],"format":"date","description":"Contract end date (YYYY-MM-DD); null when unknown."}},"required":["id","title","description","service_provider","stage","procedure_type","value","start_date","end_date"]},"ProblemDetails":{"type":"object","properties":{"type":{"type":"string","description":"Stable category identifier — clients branch on this.","format":"uri"},"title":{"type":"string","description":"Short, human-readable summary of the category. Stable per `type`."},"status":{"type":"integer","minimum":100,"maximum":599,"description":"HTTP status code, duplicated in the body so the payload is self-contained."},"detail":{"description":"Human-readable, occurrence-specific detail. Omitted on 5xx so we never leak internals.","type":"string"},"errors":{"description":"Per-field validation failures; present only on validation (400) problems.","type":"array","items":{"anyOf":[{"type":"object","properties":{"detail":{"type":"string","description":"Human-readable description of this field error."},"pointer":{"type":"string"}},"required":["detail","pointer"],"additionalProperties":false},{"type":"object","properties":{"detail":{"type":"string","description":"Human-readable description of this field error."},"parameter":{"type":"string"}},"required":["detail","parameter"],"additionalProperties":false},{"type":"object","properties":{"detail":{"type":"string","description":"Human-readable description of this field error."},"header":{"type":"string"}},"required":["detail","header"],"additionalProperties":false}]}}},"required":["type","title","status"],"additionalProperties":true}},"responses":{"Unauthenticated":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"},"example":{"type":"https://api.stotles.com/problems/unauthenticated","title":"Unauthenticated","status":401,"detail":"Missing or invalid API key."}}}},"ValidationError":{"description":"The request failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"},"example":{"type":"https://api.stotles.com/problems/validation","title":"Request validation failed","status":400,"detail":"The request parameters failed validation. See the 'errors' array for details.","errors":[{"parameter":"id","detail":"Invalid uuid"}]}}}},"NotFound":{"description":"The requested resource does not exist.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"},"example":{"type":"https://api.stotles.com/problems/not-found","title":"Not found","status":404,"detail":"No notice exists with the given id."}}}},"RateLimited":{"description":"The client has sent too many requests in a given amount of time.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"},"example":{"type":"https://api.stotles.com/problems/rate-limited","title":"Too many requests","status":429,"detail":"Rate limit exceeded. Retry later."}}}},"ServiceUnavailable":{"description":"A dependency needed to serve the request is temporarily unavailable — most often the credential check. The request can be retried unchanged; the API key is not at fault.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"},"example":{"type":"https://api.stotles.com/problems/service-unavailable","title":"Service unavailable","status":503,"detail":"The service is temporarily unavailable. Retry shortly; your API key is unaffected."}}}},"InternalError":{"description":"An unexpected error occurred.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"},"example":{"type":"https://api.stotles.com/problems/internal","title":"Internal server error","status":500}}}}}},"security":[{"apiKey":[]}]}