Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/stotles-frameworks-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no email required.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Stotles Public Frameworks API
description: "The Stotles Public 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\nEach API key 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
servers:
- url: https://api.stotles.com
description: Production
security:
- apiKey: []
tags:
- name: Frameworks
description: Framework agreements and dynamic purchasing systems.
paths:
/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'
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'
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\""
components:
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
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
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.
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.
schemas:
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
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
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
securitySchemes:
apiKey:
type: apiKey
in: header
name: x-api-key