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/dropto-run:dropto-run-deploys-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
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: Drop2Run.Api | v1 Deploys API
version: 1.0.0
description: One publish, from asking for upload addresses to putting a version live. Versions are immutable and are never written over, so promoting an earlier one is a pointer moving rather than an upload repeating.
servers:
- description: Production
url: https://dropto.run
tags:
- description: One publish, from asking for upload addresses to putting a version live. Versions are immutable and are never written over, so promoting an earlier one is a pointer moving rather than an upload repeating.
name: Deploys
paths:
/api/sites/{siteId}/deploys/prepare:
post:
operationId: PrepareDeploy
parameters:
- in: path
name: siteId
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PrepareDeployRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PrepareDeployResponse'
description: OK
'400':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Bad Request
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'503':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Service Unavailable
security:
- session: []
- accessToken: []
- claimToken: []
- {}
summary: Validates a manifest and returns one presigned upload URL per file
tags:
- Deploys
/api/sites/{siteId}/deploys/{deployId}:
get:
operationId: GetDeploy
parameters:
- in: path
name: siteId
required: true
schema:
type: string
- in: path
name: deployId
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/DeployDetail'
description: OK
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
security:
- session: []
- accessToken: []
- claimToken: []
- {}
summary: Reads the state of one deploy
tags:
- Deploys
/api/sites/{siteId}/deploys/{deployId}/complete:
post:
operationId: CompleteDeploy
parameters:
- in: path
name: siteId
required: true
schema:
type: string
- in: path
name: deployId
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
oneOf:
- type: 'null'
- $ref: '#/components/schemas/CompleteDeployRequest'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/CompleteDeployResponse'
description: OK
'400':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Bad Request
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'409':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Conflict
security:
- session: []
- accessToken: []
- claimToken: []
- {}
summary: Verifies the uploaded files and takes the deploy live
tags:
- Deploys
/api/sites/{siteId}/deploys/{deployId}/file:
get:
operationId: GetDeployFile
parameters:
- in: path
name: siteId
required: true
schema:
type: string
- in: path
name: deployId
required: true
schema:
type: string
- in: query
name: path
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/DeployFileContent'
description: OK
'400':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Bad Request
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
security:
- session: []
- accessToken: []
summary: Reads one text file out of one deploy, for the in-browser editor
tags:
- Deploys
/api/sites/{siteId}/deploys/{deployId}/manifest:
get:
operationId: GetDeployManifest
parameters:
- in: path
name: siteId
required: true
schema:
type: string
- in: path
name: deployId
required: true
schema:
type: string
- in: query
name: search
schema:
type: string
- in: query
name: cursor
schema:
type: string
- in: query
name: limit
schema:
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
- in: query
name: all
schema:
default: false
type: boolean
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/DeployManifestPage'
description: OK
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'409':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Conflict
security:
- session: []
- accessToken: []
summary: Lists the files one deploy contains, a page at a time or all at once
tags:
- Deploys
/api/sites/{siteId}/deploys/{deployId}/preview-ticket:
post:
operationId: IssuePreviewTicket
parameters:
- in: path
name: siteId
required: true
schema:
type: string
- in: path
name: deployId
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewTicket'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'503':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Service Unavailable
security:
- session: []
- accessToken: []
summary: Lets the in-browser editor's preview frame load a gated version's own files
tags:
- Deploys
/api/sites/{siteId}/deploys/{deployId}/promote:
post:
operationId: PromoteDeploy
parameters:
- in: path
name: siteId
required: true
schema:
type: string
- in: path
name: deployId
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PromoteDeployResponse'
description: OK
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'409':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Conflict
'410':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Gone
security:
- session: []
- accessToken: []
- claimToken: []
- {}
summary: Rolls the site back to an earlier deploy that still has its files
tags:
- Deploys
components:
schemas:
PrepareDeployRequest:
description: Request body of `POST /deploys/prepare`.
properties:
batches:
default: false
description: 'Whether the client can send batch permits — several small files in one request. A client that does
not set it receives one permit per file. Setting it is a request, not a guarantee: the server may
still answer with single permits only.'
type: boolean
files:
description: Every file the client intends to upload.
items:
$ref: '#/components/schemas/ManifestEntry'
minItems: 1
type: array
required:
- files
type: object
ProblemDetails:
properties:
detail:
type:
- 'null'
- string
instance:
type:
- 'null'
- string
status:
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- 'null'
- integer
- string
title:
type:
- 'null'
- string
type:
type:
- 'null'
- string
type: object
DeployManifestPage:
description: Response of `GET /sites/{siteId}/deploys/{deployId}/manifest`.
properties:
deployId:
description: ULID of the deploy the files belong to.
type: string
fileCount:
description: Files in the whole deploy, whatever the filter matched.
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
files:
description: This page of matches, ordered by path.
items:
$ref: '#/components/schemas/ManifestFile'
type: array
filesKept:
description: 'Whether the deploy is inside the retention window with its objects still on storage, the same answer
as `filesKept` on the site''s version list. The list is answerable either way — it is read from
the row — so this is what separates "these files are here" from "these files were here".'
type: boolean
matchingBytes:
description: Their total size, on the same terms.
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
matchingFiles:
description: Files the filter matched, equal to FileCount without one.
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
nextCursor:
description: Path to pass back as `cursor` for the following page, or null when this page was the last.
type:
- 'null'
- string
status:
description: Lowercase status name of that deploy.
type: string
totalBytes:
description: Size of the whole deploy, whatever the filter matched.
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
required:
- deployId
- status
- fileCount
- totalBytes
- filesKept
- matchingFiles
- matchingBytes
- files
- nextCursor
type: object
PromoteDeployResponse:
description: Response of `POST /sites/{siteId}/deploys/{deployId}/promote`.
properties:
deployId:
description: ULID of the deploy that is now live.
type: string
edge:
description: '`live` when the edge has the deploy, `pending` when the rollback is committed but the edge
write did not land yet; it gets there on its own, as on `complete`.'
type: string
fileCount:
description: Files in the promoted deploy.
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
status:
description: Always `live` on success.
type: string
totalBytes:
description: Its total size in bytes.
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
url:
description: Public URL the site answers on. Content may take up to a minute to reach every edge.
type: string
required:
- deployId
- status
- url
- fileCount
- totalBytes
- edge
type: object
DeployFileContent:
description: Response of `GET /sites/{siteId}/deploys/{deployId}/file`.
properties:
path:
description: The path, normalized — which is the spelling the manifest holds.
type: string
sha256:
description: 'Digest of the content as stored.
Sent so the editor can publish a change without re-reading anything: the new manifest is the old one
with this entry''s digest replaced, and every other file is reused by `prepare`.'
type: string
size:
description: Size in bytes, as the manifest records it.
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
text:
description: 'The file''s text, or null when the bytes are not valid UTF-8.
Null rather than a lossy decode, so the dashboard can say the file cannot be edited here instead of
offering an editor whose contents would overwrite the original with replacement characters.'
type:
- 'null'
- string
required:
- path
- sha256
- size
- text
type: object
CompleteDeployRequest:
description: Request body of `POST /deploys/{deployId}/complete`.
properties:
name:
description: 'A display name for the site, read by the client from the `<title>` of the
`index.html` being published.
Applied only to a site that has no name yet, and only on the call that takes a deploy live — so a
redeploy never renames a site, and a retried completion never renames one either.
Cleaned by SiteNames before it is stored, and dropped silently when nothing
usable is left. It is not worth failing a deploy whose files have already been verified over the
contents of a title tag, and the owner can type a name on the settings page regardless.'
type:
- 'null'
- string
type: object
PrepareDeployResponse:
description: Response of `POST /deploys/prepare`.
properties:
batchConcurrency:
description: 'How many of Batches to send at once; null when there are none. The upload Worker can
hold only six R2 writes open per request, so this is what decides how fast many small files go, and it
is set here so it can be tuned without a client release. Single permits are not affected.'
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- 'null'
- integer
- string
batches:
description: 'Batch permits, each covering several small files sent as one body. Empty unless the request asked
for batches and they are enabled; a file is in exactly one of Upload and this.'
items:
$ref: '#/components/schemas/UploadBatch'
type: array
deployId:
description: ULID of the new deploy; part of every R2 key it writes.
type: string
reused:
description: 'How many files the live deploy already holds byte-identical. These are absent from
Upload and are copied server-side when the deploy completes.'
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
total:
description: 'Files in the whole deploy: Reused plus what must be uploaded.'
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
unchanged:
default: false
description: 'True when the manifest describes exactly what is already live, so no deploy was created. The caller
has nothing to upload and must not call `complete`: DeployId is the deploy
already serving, and completing it again would only rewrite the mapping to where it already points.'
type: boolean
upload:
description: One upload permit per file sent on its own.
items:
$ref: '#/components/schemas/UploadTarget'
type: array
uploadUrl:
description: 'The single endpoint every permit is presented to. Sent with the response rather than compiled into
the client, because it is a different host in development, in tests and in production — and because
a client that knew the address without being told would still know it after we moved.'
type: string
url:
description: 'Public URL of the site, sent only when Unchanged is true. That answer is the end
of the deploy, and without it the caller would have to ask a second endpoint just to show the link.'
type:
- 'null'
- string
warnings:
description: 'Things about this deploy the caller should be told although it was accepted, or null when there are none —
today only that `_functions/` will not run on this site (`docs/briefs/FUNCTIONS-BRIEF.md` D23).'
items:
type: string
type:
- 'null'
- array
required:
- deployId
- upload
- batches
- uploadUrl
- reused
- total
type: object
UploadBatch:
description: Several small files the client sends as one body, under one permit.
properties:
files:
description: The files, in the order their bytes must follow the layout.
items:
$ref: '#/components/schemas/BatchFile'
type: array
token:
description: Bearer token authorising exactly these files.
type: string
required:
- token
- files
type: object
DeployDetail:
description: Response of `GET /sites/{siteId}/deploys/{deployId}`.
properties:
completedAt:
description: When it reached a terminal state, or null while in flight.
format: date-time
type:
- 'null'
- string
createdAt:
description: When it was prepared.
format: date-time
type: string
deployId:
description: ULID of the deploy.
type: string
error:
description: Why it failed, when it did.
type:
- 'null'
- string
fileCount:
description: Files it holds.
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
isLive:
description: Whether this is the deploy currently being served.
type: boolean
siteId:
description: ULID of its site.
type: string
status:
description: Lowercase status name.
type: string
totalBytes:
description: Its size.
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
url:
description: The site's URL, present only when this deploy is live.
type:
- 'null'
- string
required:
- deployId
- siteId
- status
- isLive
- fileCount
- totalBytes
- createdAt
- completedAt
- error
- url
type: object
ManifestEntry:
description: One entry in the client's manifest. Entirely untrusted until validated.
properties:
path:
description: Path relative to the deploy root, as the client sees it.
type:
- 'null'
- string
sha256:
description: SHA-256 of the content, lowercase hex.
type:
- 'null'
- string
size:
description: 'Exact length of the content in bytes — the length that will be uploaded. 0 only for an empty file,
whose checksum is the SHA-256 of zero bytes.'
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
required:
- path
- sha256
- size
type: object
PreviewTicket:
description: Response of `POST /sites/{siteId}/deploys/{deployId}/preview-ticket`.
properties:
action:
description: The URL to post the ticket to, as the form field `ticket`, targeting the preview frame.
type: string
expiresAt:
description: When the frame's access runs out and a new ticket is needed.
format: date-time
type: string
ticket:
description: The signed ticket. Accepted for one minute.
type: string
required:
- action
- ticket
- expiresAt
type: object
ManifestFile:
description: One file in a deploy's verified manifest.
properties:
path:
description: Its path within the site, already normalized and always /-separated.
type: string
sha256:
description: SHA-256 of the content, lowercase hex — what the upload was verified against.
type: string
size:
description: Its size in bytes.
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
required:
- path
- sha256
- size
type: object
CompleteDeployResponse:
description: Response of `POST /deploys/{deployId}/complete`.
properties:
deployId:
description: ULID of the deploy that is now live.
type: string
docsMode:
description: 'Whether the site is read through the documents viewer rather than served as files.
Reported for the same reason as Name: the server decides it, from the files this
deploy actually holds (`SiteModeDetection`), and a client that guessed from what it uploaded
would be wrong exactly when it matters — the web app that went live inside the reader because its
`index.html` sat one folder too deep, with nothing on the finished card saying so.'
type: boolean
edge:
description: '`live` when the edge has the deploy, `pending` when the deploy is live but the edge write did
not land yet — Cloudflare refused it or its API budget is spent. A pending deploy is not a failure: it
reaches the edge on its own, usually within the `Retry-After` the response carries, and calling
`complete` again is safe but not needed.'
type: string
fileCount:
description: Number of verified files.
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
modeIsManual:
description: Whether the owner chose the mode by hand, in which case no deploy changes it.
type: boolean
name:
description: 'What the site is called now, or null when it has none and its subdomain should be shown instead.
Reported rather than left for the client to infer, because only the server knows the answer: it
cleans the name it is sent, and it refuses to overwrite a name the site already had. A client that
assumed the title it sent is the name now stored would be wrong on every redeploy.
What the anonymous flow needs. A site is remembered in the browser before its first deploy starts —
the claim token is returned once and storing it cannot wait — so the name is not known at that point
and arrives here instead.'
type:
- 'null'
- string
spaMode:
description: Whether unmatched paths are answered with the site's `index.html`.
type: boolean
status:
description: Always `live` on success.
type: string
totalBytes:
description: Total verified size in bytes.
format: int64
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
url:
description: Public URL the site answers on. Content may take up to a minute to reach every edge.
type: string
required:
- deployId
- status
- url
- fileCount
- totalBytes
- name
- spaMode
- docsMode
- modeIsManual
- edge
type: object
UploadTarget:
description: Where the client should PUT one file, and what the PUT must carry.
properties:
path:
description: Normalized path, which is also what the manifest records.
type: string
sha256:
description: 'Digest signed into Token, echoed back because the client needs it to name the
file it is sending. It is the same value the client put in the manifest; returning it saves the
client from keeping its own manifest indexed by path just to find it again.'
type: string
token:
description: 'Bearer token authorising exactly this object. Signed by the control plane and verified by the upload
Worker, which refuses a second write of the same key without touching R2.'
type: string
required:
- path
- token
- sha256
type: object
BatchFile:
description: One file inside a batch.
properties:
path:
description: Normalized path, which the client uses to find the bytes and to name a failure.
type: string
sha256:
description: Digest, which is also how the layout line and the object's key are built.
type: string
required:
- path
- sha256
type: object
securitySchemes:
accessToken:
description: 'A personal access token, created at /account/tokens. Sent as `Authorization: Bearer d2r_...`. A rejected token answers 401 with `invalid_token`, which is deliberately distinct from the 403 a valid credential gets for something it may not do.'
scheme: bearer
type: http
claimToken:
description: Returned once when an anonymous site is created, and the only credential that site has until somebody signs in and claims it.
in: header
name: X-Claim-Token
type: apiKey
session:
description: The browser session, set by signing in with Google. HttpOnly, so a script cannot read it and a client outside a browser cannot send it.
in: cookie
name: d2r_session
type: apiKey