API reference.
Send a zip, get a live URL back. Plus signed webhooks and an MCP server for Claude. Start with the Quickstart.
Overview
Doope's public API publishes a .zip of a static website, live, in the same request. Doope unpacks, safety-scans, and publishes it while you wait, and the response carries the URL your project is already live at.
It publishes the same kind of project you get from dropping a file on the homepage, and you can call it from a script, a CI job, or your own tooling. Alongside Deploy, it tells you which account a key acts as, lists your projects, and registers Zapier hooks.
API host
Every API call goes to api.doope.sh, its own host apart from the Doope app at doope.sh. Projects you deploy are served from <slug>.doope.site. A path that isn't an endpoint answers 404, and a wrong method 405 with an Allow header.
Quickstart
Four steps from a built folder to a live URL.
1. Be on Solo or above
The deploy API is part of Solo, Pro, and Studio. On Free and Starter, a call to /api/v1/deploy returns 402 with upgrade: true; those plans publish from the homepage or from Claude over MCP. When a subscription ends, its API keys are revoked. See pricing for what each plan includes.
2. Create an API key
Open Settings → Developers, select Create key, and copy the key. It's shown once, so keep it in an environment variable or your CI's secrets:
3. Zip your build
Zip the contents of your build folder, so index.html sits at the root of the zip and becomes your homepage:
4. Deploy
The response carries your live URL. Run the same command again to publish a new version to the same slug. The Deploy reference covers every parameter, response, and error.
Rather skip the zip? The Doope CLI zips the folder and deploys it in one command:
Changelog
What changed in the API, the CLI and the MCP server, newest first. Changes are additive: an existing call keeps working the way it did.
October 19, 2026
- A path that isn't an endpoint answers
404, and a real path asked with the wrong method answers405with anAllowheader. Both point here. - Projects never serve
.envfiles,.gitfolders or private keys, however they were uploaded.
October 18, 2026
- The Doope CLI:
npx doope deploy ./distpublishes a folder, a zip or a file. Folder deploys leave.envfiles and keys on your machine.
October 17, 2026
- While an extra traffic payment is past due,
/api/v1/deployanswers402withpay: trueuntil it's paid. - Zapier triggers are on Solo and above.
October 6, 2026
GET /api/v1/me,GET /api/v1/projects, and Zapier hooks (POSTandDELETE /api/v1/hooks), with the Doope app on Zapier.- Deploy takes
?filename=to publish one file, and?update=1to only update an existing project.
October 5, 2026
api.doope.shis the API host.api.doope.linkkeeps working.
September 29, 2026
- Doope launches with
POST /api/v1/deploy, signed webhooks (Pro and above), and the MCP server for Claude on every plan.
Deploy from the terminal
The Doope CLI publishes a folder, a zip, or a single file and prints the live link. It calls the same Deploy API, so it needs Solo or above and an API key.
Install
Run it with npx, or install it once. Node 18 or later.
Your API key
Create one in Settings → Developers and keep it in an environment variable. --key works too.
Deploy
Deploying to a slug you own publishes a new version of that project. Folders skip .git, node_modules and .DS_Store, and secrets stay on your machine: .env files, .npmrc, .ssh/, .aws/ and key files are left out, and the CLI lists what it skipped. The link goes to stdout and everything else to stderr, so URL=$(doope deploy ./dist) captures just the link.
Commands & options
Errors print Doope's own explanation, the same as the API errors, and exit with code 1.
In CI
Deploy a project
Publishes a .zip of a static website. If ?slug= already points at a project you own, this redeploys it; otherwise a new project is created.
Endpoint
Authenticated with an API key: send it as a bearer token (or X-Api-Key):
Example request
# deploy a zipped project in one curl (--fail-with-body exits non-zero on an error) curl --fail-with-body -X POST "https://api.doope.sh/api/v1/deploy?slug=my-site" \ -H "Authorization: Bearer $DOOPE_API_KEY" \ --data-binary @site.zip
Parameters
Response
On success, 200:
Larger ZIPs return 202 with status: "processing". The URL becomes live after every batch is unpacked and scanned.
To act the moment it goes live, subscribe to the site.published webhook (Pro and above).
Update & delete
Update: deploy again with the same ?slug=. Each deploy publishes a new version of that project at the same URL, and the dashboard keeps its recent versions ready to restore.
Delete: delete a project from its page in the dashboard, or from Claude with the MCP delete_project tool.
Errors
Every error response is JSON with an error message you can log or show as-is.
Rate limits & sizes
Get the current account
Returns the account your API key acts as. Use it to check a key works, or to show who is connected.
Endpoint
Authenticated with an API key: send it as a bearer token (or X-Api-Key):
Example request
Response
On success, 200:
Errors
List projects
Returns the account's published projects, most recently updated first, up to 200. Drafts from Make that have never been published are not included.
Endpoint
Authenticated with an API key: send it as a bearer token (or X-Api-Key):
Example request
Response
On success, 200:
Errors
Subscribe a Zapier hook
Registers a Zapier REST hook, so a Zap starts when the event happens. The Doope app on Zapier calls this for you when a Zap is turned on. Each hook delivers the same body as a webhook and counts toward the account's 5 webhook endpoints. To send events to your own server, add a webhook in Integrations instead.
Endpoint
Authenticated with an API key: send it as a bearer token (or X-Api-Key):
Example request
Body
Response
201 for a new hook. Sending the same URL again updates its event and answers 200 with the same id.
Errors
Remove a Zapier hook
Removes a hook made with the subscribe call above. The Doope app on Zapier calls this when a Zap is turned off. It works on every plan, so an account can always clean up.
Endpoint
Authenticated with an API key: send it as a bearer token (or X-Api-Key):
Example request
Response
On success, 200:
Errors
Create an API key
Create API keys in the Doope app. Open Settings → Developers and select Create key (Solo and above). The key is shown once, right after you create it, so copy it somewhere safe. Doope stores only a hash of it.
Keys look like doope_<48 hex chars>. Revoke a key from Settings → Developers anytime. It stops working immediately.
Using your key
Send it as a bearer token on every request:
An X-Api-Key: doope_your_key header works too, if a Bearer header doesn't fit your tooling. Keep the key in server-side code and private config, and treat it like a password.
Any CI that runs curl can deploy. The Deploy section has a ready-to-paste GitHub Actions workflow.
Webhooks
Webhooks send your account a signed POST request the moment something happens on one of your projects. Available on Pro and above. Manage endpoints from Integrations in the app, which is also where an endpoint's signing secret is shown, once, right after you create it.
Events
Endpoint requirements
An endpoint is a public https:// URL on a hostname you control (Doope's own domains, IP addresses, and private network addresses are reserved). Up to 5 endpoints per account. Before it receives real events, an endpoint is verified: creating (or re-pointing) one sends a signed ping whose body carries a one-time challenge, which you paste back into the dashboard to show that requests to that URL reach you. Any request inspector works for this, including Webhooks by Zapier's "Catch Hook" trigger, which is also how you wire Doope into a Zap.
Endpoints keep their configuration through plan changes, and deliveries run whenever the account is on Pro or above, starting with the next event.
Headers
Events & payloads
Every delivery's body is JSON, shaped the same way regardless of event type: { id, type, created, data }. The id matches the Doope-Delivery header, and created is Unix seconds.
site.published
lead.captured
fields holds whatever extra inputs your capture form collected, or {} when there are none.
Verifying signatures
Every delivery carries a Doope-Signature header:
t is the Unix timestamp the request was signed at, and v1 is a hex-encoded HMAC-SHA256(signing secret, "{t}.{raw body}"). The timestamp is part of what's signed, so a captured request can't be replayed later under a new one. Recompute the same HMAC over the exact bytes you received (before any JSON parsing), compare it to v1 in constant time, and reject anything where t is more than a few minutes from now.
Node example
// Node 18+. req.body must be the raw, unparsed request bytes: capture
// it with express.raw({ type: "application/json" }), not express.json().
import { timingSafeEqual, createHmac } from "node:crypto";
function verifyDoopeWebhook(header, rawBody, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const given = Buffer.from(parts.v1 ?? "", "hex");
const want = Buffer.from(expected, "hex");
return given.length === want.length && timingSafeEqual(given, want);
}
// in your route handler:
if (!verifyDoopeWebhook(req.header("Doope-Signature"), req.body, process.env.DOOPE_WEBHOOK_SECRET)) {
return res.status(401).end();
}Delivery & retries
A delivery counts as successful on any 2xx response. Any other response, redirects included, is retried with exponential backoff (roughly 30s, 2m, 8m, 32m, 2h, 8.5h, then 12h), up to 8 attempts over about 24 hours, after which the delivery is marked failed. Doope reads only the status code of your response. The dashboard's "Recent deliveries" list (attempt, status, response code, duration) covers the last 7 days.
Retries resend the exact same body, so use Doope-Delivery (stable across every attempt of one event) to dedupe on your side. For example, skip processing if you've already recorded that id.
Publish from Claude (MCP)
The Doope MCP server lets Claude, or any client that speaks the Model Context Protocol, list, publish, read, update, and delete your projects right from a conversation. Same account, same projects as the dashboard, and it works on every plan, Free included.
Connecting
Every client signs in with your Doope account (OAuth). Pick the steps for yours:
For a headless setup (CI, a shared server), connect with an API key from Settings → Developers instead (Solo and above). Send it as a bearer header:
Manage connected apps anytime from Settings → Developers.