Deploy websites with an APIOne request, a live URL
REST, MCP and GitHub Actions on one API — deploy a site, read its files back and patch a single line from code, CI or any AI assistant.
https://api.dplooy.com/api/v1https://api.dplooy.com/mcp- OAuth 2.1 + PKCE
- Stateless Streamable HTTP
- Free tier
- No credit card
1curl -X POST https://api.dplooy.com/api/v1/deploy \2 -H "Authorization: Bearer dpk_live_..." \3 -H "Content-Type: application/json" \4 -d '{"html":"<h1>Hello</h1>","name":"demo"}'{
"success": true,
"url": "https://demo.dplooy.com",
"isRedeploy": false
}Deploy a website with the API in 3 steps
From zero to live website in under a minute.
- 1
Get your API key
Go to Settings → API Keys and create a new key. Copy the key — it's shown only once.
dpk_live_aBcDeFgHiJkLmNoPqRsTuVwX - 2
Deploy your site
Send your HTML to the deploy endpoint. Optionally include CSS and JS as separate strings.
bashcurl -X POST https://api.dplooy.com/api/v1/deploy \ -H "Authorization: Bearer dpk_live_..." \ -H "Content-Type: application/json" \ -d '{"html":"<h1>Hello</h1>","name":"demo"}' - 3
It's live
The API responds with your live URL. That's it — your site is deployed with SSL.
json{ "success": true, "url": "https://my-site.dplooy.com", "projectId": "a1b2c3d4-...", "isRedeploy": false, "plan": "pro", "expiresAt": null }
Authentication with API keys
All API requests require a valid API key sent as a Bearer token in the Authorization header.
Authorization: Bearer dpk_live_your_key_hereGetting a key
- 1Sign in to dplooy and go to Settings.
- 2Open the API Keys tab.
- 3Click Create API Key, give it a name, and copy the key.
Your raw API key is shown only once after creation. Store it securely — you cannot retrieve it later. If lost, revoke the key and create a new one.
- Hashed storage
- Keys are SHA-256 hashed, never stored in plain text
- Rate limited
- 30 requests per minute per IP address
- Revocable
- Revoke any key instantly from the dashboard
REST API reference
The core endpoints to deploy, manage, and inspect your hosted projects, at https://api.dplooy.com/api/v1. Forms, data, bookings, media and the rest are in the full API reference.
Deploy
/deployDeploy an HTML website from code strings. Optionally include separate CSS and JS — they'll be auto-injected into the HTML as linked files.
Request body (JSON)
| Parameter | Type | Description |
|---|---|---|
htmlrequired | string | HTML content for the page |
css | string | CSS styles — saved as style.css and linked in <head> |
js | string | JavaScript — saved as script.js and linked before </body> |
name | string | Project name for the URL (e.g. 'my-site' → my-site.dplooy.com) |
Example request
curl -X POST https://api.dplooy.com/api/v1/deploy \
-H "Authorization: Bearer dpk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"html": "<!DOCTYPE html><html><head><title>My Site</title></head><body><h1>Hello World</h1></body></html>",
"css": "h1 { color: teal; font-family: sans-serif; }",
"name": "my-site"
}'Response — 201 Created
{
"success": true,
"url": "https://my-site.dplooy.com",
"projectId": "a1b2c3d4-e5f6-...",
"isRedeploy": false,
"plan": "pro",
"expiresAt": null
}/deploy/zipDeploy a complete website from a ZIP archive. The ZIP must contain an index.html at the root. Subdirectories, CSS, JS, images, and fonts are all preserved.
Request body (multipart/form-data)
| Parameter | Type | Description |
|---|---|---|
filerequired | file | ZIP file containing the website (max 500 MB) |
name | string | Display name for the project |
projectName | string | URL slug (e.g. 'my-site' → my-site.dplooy.com) |
Example request
curl -X POST https://api.dplooy.com/api/v1/deploy/zip \
-H "Authorization: Bearer dpk_live_your_key_here" \
-F "file=@website.zip" \
-F "name=my-website" \
-F "projectName=my-website"Response — 201 Created
{
"success": true,
"url": "https://my-site.dplooy.com",
"projectId": "a1b2c3d4-e5f6-...",
"isRedeploy": false,
"plan": "pro",
"expiresAt": null,
"fileCount": 12,
"warnings": []
}Projects
/projectsList all projects for the authenticated user. Supports pagination and status filtering.
Query parameters
| Parameter | Type | Description |
|---|---|---|
page | number | Page number (default: 1) |
limit | number | Results per page (default: 20, max: 100) |
status | string | Filter by status: "active" (default) or "all" |
Example request
curl https://api.dplooy.com/api/v1/projects \
-H "Authorization: Bearer dpk_live_your_key_here"Response — 200 OK
{
"projects": [
{
"id": "a1b2c3d4-...",
"name": "My Website",
"projectName": "my-website",
"url": "https://my-website.dplooy.com",
"fileType": "html",
"hostingType": "multi-file-website",
"fileSize": 45200,
"fileCount": 3,
"views": 128,
"status": "active",
"createdAt": "2026-02-18T12:00:00.000Z",
"expiresAt": null
}
],
"total": 12,
"page": 1,
"limit": 20
}/projects/:idGet detailed information about a specific project.
Example request
curl https://api.dplooy.com/api/v1/projects/a1b2c3d4-... \
-H "Authorization: Bearer dpk_live_your_key_here"Response — 200 OK
{
"id": "a1b2c3d4-...",
"name": "My Website",
"projectName": "my-website",
"url": "https://my-website.dplooy.com",
"fileType": "html",
"hostingType": "multi-page-website",
"fileSize": 152300,
"fileCount": 12,
"views": 340,
"status": "active",
"createdAt": "2026-02-18T12:00:00.000Z",
"expiresAt": null,
"isPasswordProtected": false
}/projects/:idPermanently delete a project and all its files from storage.
Example request
curl -X DELETE https://api.dplooy.com/api/v1/projects/PROJECT_ID \
-H "Authorization: Bearer dpk_live_your_key_here"Response — 200 OK
{
"success": true,
"message": "Project deleted"
}Account
/accountGet your current plan, usage statistics, and plan limits.
Example request
curl https://api.dplooy.com/api/v1/account \
-H "Authorization: Bearer dpk_live_your_key_here"Response — 200 OK
{
"plan": "plus",
"usage": {
"projectsUsed": 8,
"projectsLimit": 25,
"storageUsed": 12500000,
"storageLimit": 524288000
},
"limits": {
"maxFileSize": 52428800,
"maxTotalStorage": 524288000,
"maxUploadSize": 524288000,
"maxProjects": 25
}
}Deploy with cURL, JavaScript or Python
Copy-paste examples to get started in your language of choice.
Deploy HTML + CSS
curl -X POST https://api.dplooy.com/api/v1/deploy \
-H "Authorization: Bearer dpk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"html": "<!DOCTYPE html><html><head><title>My Site</title></head><body><h1>Hello World</h1></body></html>",
"css": "h1 { color: teal; font-family: sans-serif; }",
"name": "my-site"
}'Deploy ZIP
curl -X POST https://api.dplooy.com/api/v1/deploy/zip \
-H "Authorization: Bearer dpk_live_your_key_here" \
-F "file=@website.zip" \
-F "name=my-website" \
-F "projectName=my-website"List Projects
curl https://api.dplooy.com/api/v1/projects \
-H "Authorization: Bearer dpk_live_your_key_here"Deploy HTML + CSS
const API_BASE = 'https://api.dplooy.com/api/v1';
const API_KEY = 'dpk_live_your_key_here';
// Deploy HTML + CSS
const res = await fetch(`${API_BASE}/deploy`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
html: '<h1>Hello World</h1>',
css: 'h1 { color: teal; }',
name: 'my-site',
}),
});
const { url, projectId } = await res.json();
console.log(`Live at: ${url}`);
// => Live at: https://my-site.dplooy.comDeploy ZIP
// Deploy a ZIP file
const form = new FormData();
form.append('file', zipFileBlob, 'website.zip');
form.append('name', 'my-website');
form.append('projectName', 'my-website');
const res = await fetch(`${API_BASE}/deploy/zip`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` },
body: form,
});
const { url, fileCount } = await res.json();
console.log(`Deployed ${fileCount} files → ${url}`);Deploy HTML + CSS
import requests
API_BASE = 'https://api.dplooy.com/api/v1'
API_KEY = 'dpk_live_your_key_here'
headers = {'Authorization': f'Bearer {API_KEY}'}
# Deploy HTML + CSS
res = requests.post(
f'{API_BASE}/deploy',
headers=headers,
json={
'html': '<h1>Hello World</h1>',
'css': 'h1 { color: teal; }',
'name': 'my-site',
},
)
data = res.json()
print(f"Live at: {data['url']}")
# => Live at: https://my-site.dplooy.comDeploy ZIP
# Deploy a ZIP file
with open('website.zip', 'rb') as f:
res = requests.post(
f'{API_BASE}/deploy/zip',
headers=headers,
files={'file': ('website.zip', f, 'application/zip')},
data={'name': 'my-website', 'projectName': 'my-website'},
)
data = res.json()
print(f"Deployed {data['fileCount']} files → {data['url']}")Deploy from GitHub Actions (CI/CD)
Auto-deploy on every push — same URL, analytics preserved. Most repos need no setup at all, and you never paste a key.
Webhook auto-deploy
Static repos — no build step
Turn on Deploy on every push in the project's Deploys tab.
- No workflow file in your repo
- No API key anywhere
- Nothing to maintain
Actions build pipeline
React, Next.js, Vite, Astro
Click Set up build & deploy in the GitHub Deploy dialog.
- Creates a dedicated API key for the repo
- Installs it as an encrypted repo secret
- Commits the workflow file
Custom workflow (optional)
For a monorepo, a custom build, or a non-GitHub CI.
- 1Repo → Settings → Secrets and variables → Actions
- 2Click New repository secret
- 3Name it
DPLOOY_API_KEY - 4Paste your
dpk_live_...key - 5Add the workflow file
# .github/workflows/deploy.yml
name: Deploy to Dplooy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Dplooy
run: |
zip -r site.zip . -x ".git/*" ".github/*" "node_modules/*" "README.md"
curl -X POST https://api.dplooy.com/api/v1/deploy/zip \
-H "Authorization: Bearer ${{ secrets.DPLOOY_API_KEY }}" \
-F "name=${{ github.event.repository.name }}" \
-F "file=@site.zip"# .github/workflows/deploy.yml
name: Build & Deploy to Dplooy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install & Build
run: npm ci && npm run build
- name: Deploy to Dplooy
run: |
cd dist # or 'build', 'out', etc.
zip -r ../site.zip .
curl -X POST https://api.dplooy.com/api/v1/deploy/zip \
-H "Authorization: Bearer ${{ secrets.DPLOOY_API_KEY }}" \
-F "name=${{ github.event.repository.name }}" \
-F "file=@../site.zip"Change cd dist to your build output folder.
MCP server for Claude, ChatGPT, Cursor and Windsurf
Two ways to connect any Model Context Protocol client — the same tools either way. The MCP server guide
Remote — no install
For claude.ai and ChatGPT: add it as a custom connector. OAuth, no API key.
https://api.dplooy.com/mcpLocal — npm package
For Claude Code, Claude Desktop, Cursor and Windsurf. Runs @dplooy/mcp-server with your API key.
claude mcp add -t stdio \
-e DPLOOY_API_KEY=dpk_live_your_key_here \
dplooy -- npx -y @dplooy/mcp-serverRestart Claude Code after adding. The dplooy tools will appear automatically.
{
"mcpServers": {
"dplooy": {
"command": "npx",
"args": ["-y", "@dplooy/mcp-server"],
"env": {
"DPLOOY_API_KEY": "dpk_live_your_key_here"
}
}
}
}macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"dplooy": {
"command": "npx",
"args": ["-y", "@dplooy/mcp-server"],
"env": {
"DPLOOY_API_KEY": "dpk_live_your_key_here"
}
}
}
}Add to .cursor/mcp.json or the IDE's MCP settings.
All MCP tools
- deploy_website
- Deploy HTML/CSS/JS to a live URL
- deploy_files
- Deploy a multi-page site by passing each file inline (remote only)
- deploy_folder
- Deploy a local folder, zipped automatically (local only)
- list_projects
- List all your deployed projects
- get_project
- Project details plus attached forms, data, bookings, chatbot and an SEO rendering check
- get_project_files
- Read a deployed site's live source files
- update_project_files
- Patch a live site — targeted string edits, explicit deletes
- delete_project
- Delete a project permanently
- get_account
- Plan, usage, limits and the per-feature availability matrix
- get_guide
- Canonical rules for any feature, read by the AI itself
- create_form
- Create a form endpoint and get the HTML snippet
- get_form
- One form endpoint: settings, assignment, submission count (never the submissions)
- list_forms
- List form endpoints and their usage
- create_data_collection
- Create a content collection from 20 presets
- get_data_collection
- Fields, rows, public URL and fetch snippet
- list_data_collections
- List collections and their assignments
- update_data_rows
- Row-level edits, appends and deletes, or a full replace
- create_booking_page
- Create a booking calendar and get the widget embed
- get_booking_page
- Read one booking page: schedule, capacity, notifications, services (read-only)
- list_booking_pages
- List booking widgets and pending requests
- upload_media
- Add up to 16 images per call, ingested by URL
- list_media
- List images in the media library
- assign_to_project
- Bind forms, collections and bookings to a project, or move them
- unassign_from_project
- Detach them — inert but intact, reattach anytime
- get_chatbot
- Read chatbot settings and the full knowledge text
- configure_chatbot
- Enable and configure the server-injected AI chatbot
- delete_form / delete_data_collection / delete_booking_page / delete_media
- Remove empty, unattached leftovers only; anything with content is refused
API rate limits and plans
API limits are based on your plan. Upgrade anytime for higher limits.
| Limit | Free$0/mo | Plus$4.99/mo | Pro$12.99/mo |
|---|---|---|---|
| Projects | 3 | 25 | Unlimited |
| Max File Size | 5 MB | 50 MB | 100 MB |
| Total Storage | 50 MB | 500 MB | 5 GB |
| Site Traffic & Bandwidth | Unlimited | Unlimited | Unlimited |
| Project Expiry | 3 days | Never | Never |
| Rate Limit | 30 req/min | 30 req/min | 30 req/min |
| API Access | |||
| Deploy History | 1 version / project | 3 versions / project |
Rate limiting is per IP address (30 requests/minute). If you hit the limit, the API returns 429 Too Many Requests. Wait 60 seconds and retry.
Error handling
All errors return JSON with an error message and a machine-readable code.
{
"error": "Invalid or revoked API key",
"code": "INVALID_API_KEY"
}| Status | Code | Description |
|---|---|---|
| 400 | — | Validation failed — the invalid fields are listed in details |
| 400 | PROJECT_LIMIT_REACHED | You've hit your plan's project limit |
| 400 | FILE_TOO_LARGE | Content exceeds your plan's file size limit |
| 400 | SECURITY_THREAT_DETECTED | Malicious content detected in HTML |
| 400 | NO_INDEX_HTML | ZIP file must contain an index.html at root |
| 400 | INVALID_FILE_TYPE | Only ZIP files are accepted for /deploy/zip |
| 401 | INVALID_API_KEY | Missing, invalid, or revoked API key |
| 404 | NOT_FOUND | Project does not exist or isn't yours |
| 409 | PROJECT_KIND_MISMATCH | Redeploy used the other endpoint — /v1/deploy updates HTML projects, /v1/deploy/zip updates ZIP and folder projects; the message names the right one |
| 409 | DEPLOY_IN_PROGRESS | Another update of the same project is still running |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests — wait 60 seconds |
| 500 | DEPLOY_FAILED | Internal error during deployment |
Website hosting API questions
How do I deploy a website from the command line?
Three steps with the REST API:
- 1Create a key in Settings → API Keys — it starts with
dpk_live_. - 2POST your HTML to
https://api.dplooy.com/api/v1/deploywith anAuthorization: Bearerheader holding the key. For multi-file sites, POST a ZIP archive to/api/v1/deploy/zip. - 3Both return a live URL immediately.
What happens when I deploy with the same project name?
Dplooy updates the existing project. Your URL stays the same, analytics are preserved, and the response includes "isRedeploy": true so your CI pipeline knows it was an update. A project keeps its kind: POST /v1/deploy updates the projects it created (HTML, optionally with CSS and JS) and POST /v1/deploy/zip updates ZIP and folder projects. A mismatch returns 409 PROJECT_KIND_MISMATCH naming the right endpoint, and a deploy that overlaps another update of the same project returns 409 DEPLOY_IN_PROGRESS.
Do I need to paste an API key into GitHub to auto-deploy?
No — not for the webhook or the build pipeline. The build pipeline mints its own key, seals it with the repo's public key before it leaves our server, and rolls it back automatically if any step of the setup fails. Need the workflow scope? Reconnect GitHub when prompted. Trigger a rebuild any time with Rebuild & deploy on the project's Deploys tab and watch the run status live. Only a custom workflow needs a key, stored as the DPLOOY_API_KEY repository secret.
Can I edit a deployed site through the API instead of redeploying it?
Yes. GET /api/v1/projects/:id/files returns the live source, and PATCH /api/v1/projects/:id/files applies targeted string edits. Only the files and text you name change; deletions require an explicit deletePaths list, so nothing is removed by omission.
What is the difference between the remote and local MCP server?
Both expose the same tool set over the same v1 API. The remote server runs on Dplooy infrastructure at https://api.dplooy.com/mcp, authenticates over OAuth 2.1 with PKCE, needs no install, and is the only option for claude.ai and ChatGPT on the web. The local server is the @dplooy/mcp-server npm package run via npx, authenticates with a dpk_live_ API key, and can additionally read files from your disk to deploy a local folder. The local key stays on your machine and is never sent to the AI provider. Both hit the same v1 endpoints, so plan limits, security scanning and rate limits apply identically.
Do I need an API key for the remote MCP server?
No. Remote connections use OAuth, so no key is created, copied or stored — the client discovers everything else itself and runs the OAuth flow. You approve the connection on a Dplooy consent screen and can revoke it from Settings → Connections; revoking takes effect on the connection's next request. API keys are required for the REST API and for local MCP installs.
What do claude.ai and ChatGPT need to use the MCP server?
Custom connectors on claude.ai need a paid Claude plan; Team and Enterprise workspaces may be admin-gated. In ChatGPT they live in developer mode. Clients cache the tool list at connect time — refresh the connector to pick up newly added tools.
Which MCP specification does Dplooy implement?
The MCP authorization specification with stateless Streamable HTTP transport, OAuth 2.1 with mandatory PKCE S256, RFC 9728 protected-resource metadata, RFC 8414 authorization-server metadata, RFC 8707 resource indicators, RFC 9207 issuer identification, and Client ID Metadata Documents with RFC 7591 dynamic client registration as a fallback.
Start deploying in seconds
Create a free account, grab an API key, and ship your first project with a single command.
No credit card required · Free plan includes 3 projects · Upgrade anytime