APIs.io Provider Control API
Claim, correct and improve your own listing. Most operations require the Influence plan; reporting that our data is wrong is free and always will be.
Claim, correct and improve your own listing. Most operations require the Influence plan; reporting that our data is wrong is free and always will be.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
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.curl "https://apis.io/api/v1/apis/apis-io-provider-control-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: APIs.io Provider Control API
version: 1.0.0
description: 'The surface a provider uses to act on their own listing: claim it, correct it, submit artifacts, dispute a finding, ask what to fix, and simulate a fix before doing the work.'
contact:
name: API Evangelist
url: https://apis.io
license:
name: CC BY 4.0
url: https://creativecommons.org/licenses/by/4.0/
servers:
- url: https://apis.io/api/v1
description: Production server.
tags:
- name: Provider Control
description: Claim, correct and improve your own listing. Most operations require the Influence plan; reporting that our data is wrong is free and always will be.
paths:
/providers/{slug}/correction:
post:
operationId: reportCorrection
summary: Report that the catalog has this provider wrong
description: 'Free, unmetered and keyless. Correcting our own error is not a paid feature.
NOT IDEMPOTENT. Each call files a new correction; sending the same body twice queues it twice. There is no caller-declared match key and the response does not distinguish a created record from an amended one, because amending is not currently possible.'
x-tier: free
x-mcp-tool: report_correction
tags:
- Provider Control
parameters:
- $ref: '#/components/parameters/Slug'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- wrong
properties:
wrong:
type: string
description: What is incorrect. Name the field if you can.
correct:
type: string
description: What it should say instead.
evidence:
type: string
format: uri
description: A URL that shows it — your own docs or site. This is what makes a correction actionable rather than a claim.
field:
type: string
description: Optional field name.
enum:
- website
- image
- api_count
- tags
- score
- access_model
- apis
relationship:
type: string
enum:
- provider
- customer
- observer
description: Never gates the report; it sets priority.
contact:
type: string
description: Where to reply. Omitted means poll status_url instead.
example:
wrong: our error_semantics dimension reads false
correct: we publish one error schema referenced across operations
evidence: https://example.com/docs/errors
field: score
relationship: provider
responses:
'202':
description: Queued for a person.
content:
application/json:
schema:
$ref: '#/components/schemas/QueuedRequest'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'503':
$ref: '#/components/responses/QueueUnreachable'
/providers/{slug}/claim:
post:
operationId: claimListing
summary: Create or return your claim on this listing
description: 'Ownership is proved against a host we already hold for the provider. A provider with no website on file cannot be claimed until a correction supplies one — the 422 says so rather than failing opaquely.
IDEMPOTENT FOR YOU, CONTESTED ACROSS PARTIES. Claiming again when you already have an open claim returns that claim (`outcome: already_claimed`), not a second one. A claim on a listing ANOTHER party has already claimed is a 409 — that is a dispute a person decides, and telling you your claim was progressing when it is someone else''s would be a lie.'
x-tier: business
x-mcp-tool: claim_listing
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
contact:
type: string
responses:
'202':
description: Claim queued for verification.
content:
application/json:
schema:
$ref: '#/components/schemas/QueuedRequest'
'200':
description: You already have an open claim on this listing. This is that claim.
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertResult'
'402':
$ref: '#/components/responses/UpgradeRequired'
'409':
description: Another party has an open claim on this listing. A person decides it.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: No provable host on file, so the claim cannot be checked.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
$ref: '#/components/responses/QueueUnreachable'
/providers/{slug}/facts:
post:
operationId: correctFacts
summary: Create or update your pending fact correction for this listing
description: 'Structured corrections an operator applies by hand. Send one or more of the fields below.
AN UPSERT, scoped to you. While you have an open correction for this provider a second call AMENDS it in place and keeps its id, so you keep polling the same status_url and an operator works one currently-correct row rather than reconciling three. `outcome` says which happened: `created` (202) or `amended` (200), with `previous` carrying what was replaced.
Scoped to the submitter deliberately: a different person correcting the same provider files their own request, because two people disagreeing about a listing is something a human must see rather than a silent overwrite.'
x-tier: business
x-mcp-tool: correct_facts
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
requestBody:
required: true
content:
application/json:
schema:
type: object
minProperties: 1
description: One or more of the properties below.
properties:
name:
type: string
description:
type: string
url:
type: string
format: uri
industries:
type: array
items:
type: string
tags:
type: array
items:
type: string
contact:
type: string
responses:
'200':
description: Your open correction for this provider was amended in place. Same id.
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertResult'
'202':
description: Filed as a new request.
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertResult'
'400':
$ref: '#/components/responses/BadRequest'
'402':
$ref: '#/components/responses/UpgradeRequired'
'503':
$ref: '#/components/responses/QueueUnreachable'
/providers/{slug}/submit:
post:
operationId: submitArtifact
summary: Create or update an artifact pointer for this listing
description: 'Point us at an artifact you publish — an OpenAPI, an AsyncAPI, a rules file — and it is fetched and wired by an operator.
UPSERT ON (type, url). Submitting a pointer we already hold — same type AND same url — is a no-op that says so (`outcome: unchanged`), and nothing is queued. Submitting a NEW url of a type we already hold is an ADDITION, not a replacement: providers legitimately publish several specs, and silently replacing one would remove an artifact you are already scored for, so a submission meant to raise a score would lower it. `existing_of_type` tells you how many we already hold.'
x-tier: business
x-mcp-tool: submit_artifact
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- type
- url
properties:
type:
type: string
description: Artifact type
e.g. OpenAPI: null
AsyncAPI: null
Rules.: null
url:
type: string
format: uri
contact:
type: string
example:
type: OpenAPI
url: https://example.com/openapi.yml
responses:
'200':
description: We already hold that exact pointer. Nothing was queued.
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertResult'
'202':
description: Queued as an addition.
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertResult'
'400':
$ref: '#/components/responses/BadRequest'
'402':
$ref: '#/components/responses/UpgradeRequired'
'503':
$ref: '#/components/responses/QueueUnreachable'
/providers/{slug}/visibility:
post:
operationId: setVisibility
summary: Request restricted listing or removal
description: A person applies this — it strips artifacts, pages and rollups across the network.
x-tier: business
x-mcp-tool: set_visibility
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- visibility
properties:
visibility:
type: string
enum:
- restricted
- delisted
description: restricted — name, description and a link to your own site, unrated and out of every ranked view. delisted — removed from the catalog entirely.
reason:
type: string
contact:
type: string
responses:
'202':
description: Queued and prioritised.
content:
application/json:
schema:
$ref: '#/components/schemas/QueuedRequest'
'400':
$ref: '#/components/responses/BadRequest'
'402':
$ref: '#/components/responses/UpgradeRequired'
'503':
$ref: '#/components/responses/QueueUnreachable'
/providers/{slug}/dispute:
post:
operationId: disputeFinding
summary: Dispute something the rating says about this provider
description: '"You say I lack X, here it is." Open to any paying caller rather than owners only: requiring a claim first would mean the people most motivated to fix a wrong score have to wait on a manual verification before they can tell us we are wrong.'
x-tier: business
x-mcp-tool: dispute_finding
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- claim
properties:
claim:
type: string
evidence_url:
type: string
format: uri
contact:
type: string
example:
claim: you say we have no OpenAPI
evidence_url: https://example.com/openapi.yml
responses:
'202':
description: Filed. A person fetches your evidence and emails you either way.
content:
application/json:
schema:
$ref: '#/components/schemas/QueuedRequest'
'400':
$ref: '#/components/responses/BadRequest'
'402':
$ref: '#/components/responses/UpgradeRequired'
'503':
$ref: '#/components/responses/QueueUnreachable'
/providers/{slug}/generate:
post:
operationId: generateArtifacts
summary: What APIs.io can generate on this provider's behalf
description: Reports which artifacts we can author for this provider and how to ask for them. Read-only despite the verb.
x-tier: business
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
responses:
'200':
description: What is available.
content:
application/json:
schema:
type: object
properties:
slug:
type: string
name:
type: string
available:
type: array
items:
type: string
usage:
type: string
'402':
$ref: '#/components/responses/UpgradeRequired'
/providers/{slug}/projection:
post:
operationId: simulateFixes
summary: What a set of fixes would move the score to
description: A dry run. Nothing is stored and nothing is queued — the verb is POST because the fix list is a body, not because this writes.
x-tier: business
x-mcp-tool: simulate_fixes
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- fixes
properties:
fixes:
type: array
items:
type: string
description: Check or dimension ids
as returned by /remediation.: null
example:
fixes:
- error_semantics
responses:
'200':
description: The projected score, and which fixes were rejected as unmodellable.
content:
application/json:
schema:
type: object
properties:
slug:
type: string
applied:
type: array
items:
type: string
rejected:
type: array
items:
type: string
from:
type: number
to:
type: number
score_gain:
type: number
band_changed:
type: boolean
model_drift:
type: string
model_drift_note:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'402':
$ref: '#/components/responses/UpgradeRequired'
/providers/{slug}/remediation:
get:
operationId: whatCanIFix
summary: The ranked, costed punch list for this provider
description: One ordered list across both rating layers. `do_first` prefers a band gate over any amount of points, because points cannot clear a gate.
x-tier: business
x-mcp-tool: what_can_i_fix
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
responses:
'200':
description: Ranked items, gates, and the headline.
content:
application/json:
schema:
type: object
properties:
slug:
type: string
current:
type: object
do_first:
type: object
gates:
type: object
items:
type: array
items:
type: object
properties:
kind:
type: string
enum:
- check
- facet
description: A named check
or a facet rollup where no check data explains that facet.: null
layer:
type: string
enum:
- kin_score
- agent_readiness
id:
type: string
score_gain:
type: number
description: Composite points
not raw rubric points.: null
what_satisfies_it:
type: string
'402':
$ref: '#/components/responses/UpgradeRequired'
/providers/{slug}/gates:
get:
operationId: readinessGates
summary: Band gates for this provider, and what is unmet
x-tier: business
x-mcp-tool: readiness_gates
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
responses:
'200':
description: Current band, the next band, and every gate requirement with its status.
content:
application/json:
schema:
$ref: '#/components/schemas/ReadinessGates'
'402':
$ref: '#/components/responses/UpgradeRequired'
/providers/{slug}/rating/checks:
get:
operationId: providerRatingChecks
summary: Per-check Kin Score results for this provider
description: Actionable checks only — missed and partial. `counts` reports all four statuses so a reader can verify nothing is hidden. Ordered by points available.
x-tier: business
tags:
- Provider Control
security:
- ApiKeyAuth: []
parameters:
- $ref: '#/components/parameters/Slug'
responses:
'200':
description: The per-check results, joined against the rubric.
content:
application/json:
schema:
type: object
properties:
slug:
type: string
scored_at:
type: string
rubric_version:
type: string
counts:
type: object
checks:
type: array
items:
type: object
properties:
id:
type: string
status:
type: string
enum:
- missed
- partial
label:
type: string
facet:
type: string
points_available:
type: number
what_satisfies_it:
type: string
'402':
$ref: '#/components/responses/UpgradeRequired'
'404':
$ref: '#/components/responses/NotFound'
'503':
description: Per-check results are not loaded for this build. A gap in our data, not a statement that you failed nothing.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/checks:
post:
operationId: requestCheck
summary: Ask for a provider, industry, tag or area to be re-profiled
description: A check means re-running the enrichment pipeline against a live surface — a human-supervised job. The request takes a place in a queue rather than returning an answer.
x-tier: business
x-mcp-tool: request_check
tags:
- Provider Control
security:
- ApiKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
slug:
type: string
url:
type: string
format: uri
targetType:
type: string
enum:
- provider
- industry
- tag
- area
- estate
- catalog
kind:
type: string
notes:
type: string
contact:
type: string
responses:
'200':
description: Queued.
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
queued:
type: boolean
detail:
type: string
'402':
$ref: '#/components/responses/UpgradeRequired'
'503':
$ref: '#/components/responses/QueueUnreachable'
/gaps/report:
post:
operationId: reportGap
summary: Tell us what you looked for and did not find
description: Keyless and free on purpose — a gap report that must be paid for is a report we do not get.
x-tier: free
x-mcp-tool: report_gap
tags:
- Provider Control
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- looked_for
properties:
looked_for:
type: string
context:
type: string
contact:
type: string
responses:
'202':
description: Received.
content:
application/json:
schema:
type: object
properties:
received:
type: boolean
'400':
$ref: '#/components/responses/BadRequest'
'503':
$ref: '#/components/responses/QueueUnreachable'
components:
schemas:
Error:
type: object
properties:
error:
type: string
detail:
type: string
QueuedRequest:
type: object
description: Every write here is a REQUEST, not a completed action. `completed` is always false on acceptance.
properties:
received:
type: boolean
completed:
type: boolean
request_type:
type: string
slug:
type: string
id:
type: string
description: Poll status_url with this.
status:
type: string
status_url:
type: string
detail:
type: string
UpsertResult:
type: object
description: A write whose repeat behaviour is defined. `outcome` names which branch ran, so a caller retrying after a timeout can tell what the server did without re-reading the record.
allOf:
- $ref: '#/components/schemas/QueuedRequest'
- type: object
properties:
outcome:
type: string
enum:
- created
- amended
- unchanged
- already_claimed
description: created — a new request. amended — your open one was replaced, same id. unchanged — we already hold this, nothing queued. already_claimed — your existing claim, not a second.
previous:
type: object
description: On an amend
what the request held before.: null
revisions:
type: integer
description: How many times this request has been amended.
existing_of_type:
type: integer
description: On submit
how many pointers of this type we already hold.: null
BandGate:
type: object
description: One band's score floor and the gate guarding it.
properties:
band:
type: string
enum:
- agent-native
- agent-ready
- agent-aware
- human-only
maxLength: 1024
label:
type: string
maxLength: 256
min:
type: number
description: Score floor for this band.
points_short:
type: integer
description: Points still needed to reach the floor. 0 once the floor is met.
gated:
type: boolean
description: Whether this band carries a gate at all.
gate_requires:
type: array
description: Dimensions the gate requires.
items:
type: string
maxLength: 128
gate_met:
type: array
description: Required dimensions this provider satisfies.
items:
type: string
maxLength: 128
gate_unmet:
type: array
description: Required dimensions still missing. Empty when the gate is satisfied.
items:
type: string
maxLength: 128
gate_satisfied:
type: boolean
demote_to:
type: string
description: Band a provider falls to when the gate is not satisfied.
maxLength: 128
blocking:
type: array
description: What is actually holding this provider out of the band — the score, the gate, or both.
items:
type: string
maxLength: 256
rationale:
type: string
description: Why this band is gated the way it is.
maxLength: 4096
additionalProperties: true
ReadinessGates:
type: object
description: What stands between this listing and the next agent-readiness band. Agent Readiness is additive, so a provider can reach a band's score floor and still be held below it by the band GATE — this says which, and what would satisfy it.
required:
- slug
- name
- current_band
- current_score
properties:
slug:
type: string
maxLength: 128
name:
type: string
maxLength: 256
current_score:
type: number
minimum: 0
maximum: 100
current_band:
type: string
enum:
- agent-native
- agent-ready
- agent-aware
- human-only
maxLength: 1024
band_gated_from:
type: string
description: The band this provider SCORED into but was demoted from by the gate. Absent when no demotion applied — a provider held at its scored band was not gated.
enum:
- agent-native
- agent-ready
- agent-aware
- human-only
maxLength: 1024
verdict:
type: string
description: One line saying where the provider stands and why.
maxLength: 2048
next_band:
$ref: '#/components/schemas/BandGate'
all_bands:
type: array
description: Every band with its floor and gate, so the whole ladder is visible at once.
items:
$ref: '#/components/schemas/BandGate'
additionalProperties: true
responses:
QueueUnreachable:
description: The request queue is not reachable. The response says where else to reach us — a request here is never dropped silently.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
BadRequest:
description: The body did not carry what this operation needs. The response names the fields.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: No such provider, or nothing stored for it.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
UpgradeRequired:
description: A valid credential below the required plan. An unauthenticated caller gets 401 with a bootstrap challenge instead.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
parameters:
Slug:
name: slug
in: path
required: true
description: The provider slug the record is filed under.
schema:
type: string
example: apis-io
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: x-api-key