Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: AICD Data reports API
version: 1.0.0
contact:
name: AICD API
url: https://aicdapi.com
email: hello@aicdapi.com
x-publisher:
'@id': https://cairn-labs.com/#organization
description: 'Structured Dallas-Fort Worth civic records. Public endpoints retain their documented cache and IP limits. Customer endpoints under /api/v1/data require a server bearer credential and always return Cache-Control: no-store. Customer grants, request/burst/export limits and response size caps are enforced. v1 allows additive response fields; breaking changes use a new version with a minimum 90-day migration notice during the first-customer pilot. Source check time and processing state describe observed coverage; no uptime or completeness guarantee is implied.'
servers:
- url: /
description: Same origin as this document
security: []
tags:
- name: Data reports
description: Report a missing public record and follow what happened to the report.
paths:
/api/v1/data-reports:
post:
tags:
- Data reports
security:
- ApiCustomerBearer: []
x-any-active-credential: true
x-release-status: limited
operationId: submitDataReport
summary: Report one missing public record
description: 'Limited release. Any active API key can submit a report; no scope and no report permission are required, and the account needs current paid access: a confirmed current paid subscription period, or a confirmed API payment within the last 30 days on the pay-as-you-go path. A report takes no extra payment and does not consume paid data-call usage. Saves a report and validation job together; intake does not fetch the source or call a model. A 202 response confirms receipt, not a verified gap or promised fix. Reuse the same Idempotency-Key and body after a lost response. Report limits apply across keys, REST, and MCP.'
x-max-request-body-bytes: 8192
parameters:
- in: header
name: Idempotency-Key
required: true
description: A caller-chosen retry token. Reuse only for the same request body.
schema:
type: string
minLength: 1
maxLength: 128
pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$
example: example-retry-token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportInput'
example:
sourceUrl: https://example.gov/meetings/2026-09-01-council-agenda
expectedRecord: The September 1, 2026 council agenda packet for the regular session.
responses:
'202':
description: Report durably saved, or the original submission receipt returned.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportReceiptEnvelope'
'400':
description: The report input or report ID is invalid.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'401':
description: The API key is missing, invalid, expired, or revoked.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'403':
description: The credential or workspace is not allowed to report.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'409':
description: The Idempotency-Key was used with a different request body.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'413':
description: The streamed request body exceeds 8 KiB.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'429':
description: A report limit was reached, or the account-wide abuse ceiling was reached. The abuse ceiling is account-wide and is not charged against the paid quota. Retry after the stated delay.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
Retry-After:
description: Whole seconds to wait before a bounded retry.
schema:
type: integer
minimum: 1
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'503':
description: A required access, limit, policy, or queue control is unavailable.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
x-auth-class: bearer_api_key
x-markdown-url: /api-reference/submitDataReport.md
x-curl-example: "curl -X POST 'https://aicdapi.com/api/v1/data-reports' \\\n -H \"Authorization: Bearer $AICD_API_KEY\" \\\n -H 'Idempotency-Key: example-retry-token' \\\n -H 'Content-Type: application/json' \\\n --data '{\"sourceUrl\":\"https://example.gov/meetings/2026-09-01-council-agenda\",\"expectedRecord\":\"The September 1, 2026 council agenda packet for the regular session.\"}'"
x-caching: no-store.
x-notes:
- 'Any active API key can call this operation; no scope and no report permission are required. The account needs current paid access: a confirmed current paid subscription period, or a confirmed API payment within the last 30 days on the pay-as-you-go path. Nothing here consumes paid data-call usage, and the report limits are separate from the paid data-call allowance.'
- A 202 response confirms receipt, not a verified gap or a promised fix.
- 'Limited release: available to an account with current paid access and any active API key.'
x-retry-after: Sent on 429 only, as whole seconds.
x-errors:
- status: 400
code: invalid_input
- status: 401
code: unauthorized
- status: 403
code: forbidden
- status: 409
code: replay_conflict
- status: 413
code: invalid_input
- status: 429
code: rate_limited
- status: 429
code: report_limit_reached
- status: 429
code: submit_rate_limited
- status: 503
code: authentication_unavailable
/api/v1/data-reports/{reportId}:
get:
tags:
- Data reports
security:
- ApiCustomerBearer: []
x-any-active-credential: true
x-release-status: limited
operationId: getDataReport
summary: Check your missing-data report
description: 'Limited release. Any active API key can check a report, with the same access as submission: no scope and no report permission, and the account needs current paid access. A status read takes no extra payment. Returns only this customer''s report and safe findings. Other-customer IDs are treated as not found. Follow nextCheckAt instead of polling in a loop. A status read does not consume paid data-call usage.'
parameters:
- in: path
name: reportId
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The customer's current report status.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportStatusEnvelope'
'400':
description: The report input or report ID is invalid.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'401':
description: The API key is missing, invalid, expired, or revoked.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'403':
description: The credential or workspace is not allowed to report.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'404':
description: No report with that ID is available to this customer.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'429':
description: A report limit was reached, or the account-wide abuse ceiling was reached. The abuse ceiling is account-wide and is not charged against the paid quota. Retry after the stated delay.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
Retry-After:
description: Whole seconds to wait before a bounded retry.
schema:
type: integer
minimum: 1
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
'503':
description: A required access, limit, policy, or queue control is unavailable.
headers:
Cache-Control:
description: Customer report responses must not be cached.
schema:
type: string
const: no-store
content:
application/json:
schema:
$ref: '#/components/schemas/DataReportErrorEnvelope'
x-auth-class: bearer_api_key
x-markdown-url: /api-reference/getDataReport.md
x-curl-example: "curl -X GET 'https://aicdapi.com/api/v1/data-reports/{reportId}' \\\n -H \"Authorization: Bearer $AICD_API_KEY\""
x-caching: no-store.
x-notes:
- 'Any active API key can call this operation; no scope and no report permission are required. The account needs current paid access: a confirmed current paid subscription period, or a confirmed API payment within the last 30 days on the pay-as-you-go path. Nothing here consumes paid data-call usage, and the report limits are separate from the paid data-call allowance.'
- 'Limited release: available to an account with current paid access and any active API key.'
x-retry-after: Sent on 429 only, as whole seconds.
x-errors:
- status: 400
code: invalid_input
- status: 401
code: unauthorized
- status: 403
code: forbidden
- status: 404
code: report_not_found
- status: 429
code: rate_limited
- status: 429
code: status_rate_limited
- status: 503
code: authentication_unavailable
components:
schemas:
DataReportErrorEnvelope:
type: object
properties:
error:
type: object
properties:
code:
type: string
enum:
- unauthorized
- forbidden
- authentication_unavailable
- rate_limited
- request_too_large
- invalid_input
- access_denied
- paid_access_required
- paid_policy_unavailable
- submit_rate_limited
- report_limit_reached
- status_rate_limited
- intake_paused
- worker_paused
- queue_unavailable
- replay_conflict
- report_not_found
- service_unavailable
- budget_exhausted
- lease_conflict
- state_conflict
- invalid_transition
- resolution_incomplete
message:
type: string
minLength: 1
required:
- code
- message
additionalProperties: false
required:
- error
additionalProperties: false
DataReportStatusEnvelope:
type: object
properties:
data:
type: object
properties:
reportId:
type: string
format: uuid
pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
status:
type: string
enum:
- received
- validating
- investigating
- fixing
- verifying
- resolved
- needs_review
- not_missing
- out_of_coverage
- unable_to_verify
submittedAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
updatedAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
closedAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
nextCheckAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
reasonCode:
type: string
enum:
- already_present
- query_mismatch
- publication_delay
- coverage_gap
- discovery_failure
- fetch_failure
- extraction_failure
- classification_failure
- search_index_failure
- feed_sync_failure
- unverified
finding:
type: string
minLength: 1
maxLength: 1000
nextAction:
type: string
minLength: 1
maxLength: 500
verifiedRecords:
maxItems: 20
type: array
items:
type: object
properties:
itemId:
type: string
format: uuid
pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
sourceUrl:
type: string
minLength: 1
maxLength: 2048
title:
type: string
minLength: 1
maxLength: 300
required:
- itemId
- sourceUrl
additionalProperties: false
required:
- reportId
- status
- submittedAt
- updatedAt
- verifiedRecords
additionalProperties: false
required:
- data
additionalProperties: false
DataReportInput:
type: object
properties:
sourceUrl:
type: string
minLength: 1
maxLength: 2048
expectedRecord:
type: string
minLength: 1
maxLength: 1000
jurisdictionSlug:
type: string
minLength: 1
maxLength: 100
pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
recordKind:
type: string
enum:
- agenda
- record_stream
recordDate:
type: string
format: date
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))$
sourceRecordId:
type: string
minLength: 1
maxLength: 200
pattern: ^[A-Za-z0-9][A-Za-z0-9._:/-]*$
queryContext:
type: object
properties:
searchTerms:
type: string
minLength: 1
maxLength: 200
filters:
type: object
properties:
jurisdictionSlug:
type: string
minLength: 1
maxLength: 100
pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
bodySlug:
type: string
minLength: 1
maxLength: 100
pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
topicSlug:
type: string
minLength: 1
maxLength: 100
pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
recordKind:
type: string
enum:
- agenda
- record_stream
dateFrom:
type: string
format: date
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))$
dateTo:
type: string
format: date
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))$
sourceSystem:
type: string
minLength: 1
maxLength: 200
pattern: ^[A-Za-z0-9][A-Za-z0-9._:/-]*$
sourceRecordId:
type: string
minLength: 1
maxLength: 200
pattern: ^[A-Za-z0-9][A-Za-z0-9._:/-]*$
additionalProperties: false
surface:
oneOf:
- type: object
properties:
kind:
type: string
const: rest
route:
type: string
enum:
- /api/v1/agenda/search
- /api/v1/agenda/search-facets
- /api/v1/agenda/items/{itemId}
- /api/v1/data/changes
- /api/v1/data/snapshots
- /api/v1/data/snapshots/{snapshotId}/{resource}
- /api/v1/data/batch
- /api/v1/public/agenda-hits
- /api/v1/public/agenda-hits/{matchId}
- /api/v1/public/upcoming-agenda-hits
- /api/v1/public/coverage
- /api/v1/public/source-status
required:
- kind
- route
additionalProperties: false
- type: object
properties:
kind:
type: string
const: mcp
tool:
type: string
enum:
- search_agenda
- get_agenda_item
- get_coverage
- get_data_coverage
- get_source_status
- get_upcoming_agenda_hits
- get_agenda_hit
- get_jurisdiction_meeting_cadence
required:
- kind
- tool
additionalProperties: false
required:
- surface
additionalProperties: false
requestId:
type: string
minLength: 1
maxLength: 128
pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$
required:
- sourceUrl
- expectedRecord
additionalProperties: false
description: Send one public source URL and a short description. Input is also checked for unsafe hosts, URL credentials, secret-like query parameters, and supported route/tool values. Source text is evidence, not instructions.
DataReportReceiptEnvelope:
type: object
properties:
data:
type: object
properties:
reportId:
type: string
format: uuid
pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
status:
type: string
const: received
statusUrl:
type: string
minLength: 1
maxLength: 2048
submittedAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
nextCheckAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
required:
- reportId
- status
- statusUrl
- submittedAt
- nextCheckAt
additionalProperties: false
required:
- data
additionalProperties: false
securitySchemes:
ApiCustomerBearer:
type: http
scheme: bearer
bearerFormat: Opaque service credential
description: Server-only customer key. civic:read covers changes, batch and health. civic:export covers snapshot creation and pages. Keep test and production keys separate.
x-aicd-reference:
human: /api-reference
markdown: /api-reference.md
operationMarkdownTemplate: /api-reference/{operationId}.md
openApi: /api/openapi.json
llmsIndex: /llms.txt
llmsFull: /llms-full.txt
x-aicd-mcp:
transport:
paths:
- /api/v1/mcp
methods:
- POST
protocol: 'Streamable HTTP carrying JSON-RPC 2.0 over HTTPS. The same path serves two protocol eras. A current-era request identifies itself in the body with a params._meta envelope claim (io.modelcontextprotocol/protocolVersion) together with protocolVersion and clientCapabilities, and is answered with one JSON response. A POST without that envelope is treated as a 2025-era request: it is answered per request with no session, and the reply is an SSE stream whose data frames carry the JSON-RPC result. JSON-RPC batch arrays are accepted only on the 2025-era path; a batch containing a current-era element is refused. The server never issues an Mcp-Session-Id, so nothing has to be kept between calls. Only tools are exposed: there are no resources and no prompts. Clients use initialize, tools/list and tools/call; server/discover reports the supported revision.'
headers:
- 'Authorization: Bearer <aicd_... API key> - required on every request. The key must grant mcp:read. A browser session is not accepted here.'
- 'Content-Type: application/json - required. Any other media type is refused with HTTP 415.'
- 'Accept: application/json and text/event-stream - required on a 2025-era request, and both media types must be listed; otherwise HTTP 406. Not checked on a 2026-07-28 request.'
- MCP-Protocol-Version - optional. On a 2025-era request it must be one of 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05 or 2024-10-07. On a request carrying the 2026-07-28 envelope claim it must be 2026-07-28 and must equal the body claim.
- Mcp-Method - required on a 2026-07-28 request and must agree with the JSON-RPC method in the body; a disagreement is refused.
- Mcp-Name - required on a 2026-07-28 tools/call and must equal params.name.
- Origin - optional, but when sent its hostname must match the hostname of the request URL, otherwise HTTP 403. A cross-site browser write is refused before the route runs.
- Content-Length - optional, but when sent it must parse as a non-negative integer and must not exceed 65,536; otherwise HTTP 400 or HTTP 413.
- Mcp-Session-Id - never issued and never required. The transport is stateless, so send none.
sizeLimit: 65,536 bytes for the whole request body, enforced both on the declared Content-Length and on the streamed body (HTTP 413 request_too_large). Civic tool results are separately capped at 16,384 bytes; a result that cannot fit is trimmed, and a result that still cannot fit fails with the tool error response_too_large rather than being returned partially. The REST data-report routes have their own 8 KiB body limit, which does not apply to a submission sent inside an MCP request.
auth:
class: bearer_api_key
scopes:
- mcp:read
note: 'Send an opaque AICD API key as `Authorization: Bearer aicd_...`. The same valid key serves the records API and MCP, and every stored key carries the MCP read scope, including tools/list. The two report tools ask for no report permission and never use the paid civic executor or take an extra payment, and the account still needs current paid access. The tool list itself is static: all five tools are always listed, and the difference between accounts is per call, not per list - a civic tool call is billed or refused according to the account''s billing channel (pay-as-you-go settlement, a live subscription period, or an operator channel that rejects payment metadata). Authentication happens before the MCP handler runs and can fail with HTTP 401 unauthorized, HTTP 403 forbidden or a billing code, or HTTP 503 authentication_unavailable; a handler failure returns HTTP 503 mcp_unavailable. Every route response carries Cache-Control: no-store. The separate route /api/mcp is a closed legacy stub that always returns HTTP 403 mcp_prelaunch with no credential check and is not an MCP surface; it is not an alias of /api/v1/mcp.'
rateLimit: 'On the metered path, a message from an account bound to a subscription that is not a `tools/call` consumes two per-account transport buckets: a minute bucket (60-second window, default 120 requests) and a burst bucket (1-second window, default 30 requests), at the account''s own allowances, which the account console and the public usage limits help show. On exhaustion the request fails with HTTP 429 rate_limited and a Retry-After header carrying whole seconds until the current fixed window ends, minimum 1. A civic `tools/call` is not counted here: the paid quota path charges it. A message from an account on another billing channel is not counted here either. An allowlisted metadata message (`initialize`, `tools/list`, `ping`, `server/discover`, `notifications/initialized`, `notifications/cancelled`) and one of the two report tools take neither bucket: they share one admission instead, a valid key with mcp:read and then a fail-closed per-client-IP report edge limit that refuses with 429 rate_limited and a Retry-After, or with 503 when it cannot be checked. For a report that admission is abuse control only, because the report still needs the account''s current paid access. Report counters surface as tool errors with retryAfterSeconds inside the payload instead of HTTP 429: 5 submissions per account-minute, 30 status reads per account-minute, 20 new reports per account-day, and 20 unresolved reports.'
releaseStatus: limited
tools:
# --- truncated at 32 KB (82 KB total) ---
# Full source: https://artifacts.apis.io/aicdapi-com/openapi/aicdapi-com-data-reports-api-openapi.yml