# The Website Export API

> REST API to export Framer, Webflow, Wix, Squarespace and WordPress sites to static HTML. Start jobs, poll status, download ZIPs. In Pro and Agency.

Canonical: https://www.nocodeexport.com/en/developer-api

Everything the exporter does — animations recovered, badges stripped, forms rewired — behind three REST endpoints. Start a job, poll until done, download the ZIP.

## Quickstart

### cURL

```bash
# 1 — start an export
curl -X POST https://www.nocodeexport.com/api/v1/exports \
  -H "Authorization: Bearer nce_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://your-site.framer.website", "mode": "full-site" }'
# → 202 { "jobId": "...", "status": "pending", "statusUrl": "..." }

# 2 — poll until done
curl https://www.nocodeexport.com/api/v1/exports/JOB_ID \
  -H "Authorization: Bearer nce_live_YOUR_KEY"
# → { "status": "completed", "percent": 100,
#     "result": { "zipUrl": "https://…", "pagesExported": 14 } }

# 3 — download result.zipUrl with the same API key
curl https://www.nocodeexport.com/api/v1/exports/JOB_ID/download \
  -H "Authorization: Bearer nce_live_YOUR_KEY" \
  --fail --output export.zip
```

### Node.js

```js
import { writeFile } from "node:fs/promises";

const API = "https://www.nocodeexport.com/api/v1";
const KEY = process.env.NCX_API_KEY; // nce_live_...
const headers = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };

// Start the export.
const start = await fetch(`${API}/exports`, {
  method: "POST",
  headers,
  body: JSON.stringify({ url: "https://your-site.framer.website", mode: "full-site" }),
}).then((r) => r.json());

// Poll until it finishes.
let job;
do {
  await new Promise((r) => setTimeout(r, 2500));
  job = await fetch(start.statusUrl, { headers }).then((r) => r.json());
} while (!["completed", "failed"].includes(job.status));

if (job.status !== "completed" || !job.result.zipUrl) throw new Error(job.error || "Export unavailable");
const zip = await fetch(job.result.zipUrl, { headers });
if (!zip.ok) throw new Error(`Download failed: ${zip.status}`);
await writeFile("export.zip", Buffer.from(await zip.arrayBuffer()));
```

### Python

```python
import os, time, requests

API = "https://www.nocodeexport.com/api/v1"
headers = {"Authorization": f"Bearer {os.environ['NCX_API_KEY']}"}

# Start the export.
start = requests.post(
    f"{API}/exports",
    headers=headers,
    json={"url": "https://your-site.framer.website", "mode": "full-site"},
).json()

# Poll until it finishes.
while True:
    time.sleep(2.5)
    job = requests.get(start["statusUrl"], headers=headers).json()
    if job["status"] in ("completed", "failed"):
        break

if job["status"] != "completed" or not job["result"]["zipUrl"]:
    raise RuntimeError(job.get("error") or "Export unavailable")
with requests.get(job["result"]["zipUrl"], headers=headers, stream=True) as zip:
    zip.raise_for_status()
    with open("export.zip", "wb") as file:
        for chunk in zip.iter_content(chunk_size=65536):
            file.write(chunk)
```

## Built on the production export engine

The API is a thin layer over the same pipeline that has shipped every dashboard export — not a separate, lesser crawler.

### Async jobs on real browsers

Every export renders in a real headless browser on dedicated machines. Jobs run in the background and survive client disconnects — poll whenever.

### Same output as the dashboard

Scroll animations recovered, platform badges and trackers stripped, forms rewired, assets handled per your plan. Identical ZIPs, programmatic trigger.

### One quota, no surprises

API exports draw from the same monthly quota as your dashboard exports, with plan limits enforced transparently — downgrades are reported, never silent.

## Endpoints

| Method | Endpoint | Description |
| --- | --- | --- |
| POST | `/api/v1/exports` | Start an export job — returns 202 with a jobId and statusUrl. |
| GET | `/api/v1/exports/{jobId}` | Job status with live percent; completed jobs include result.zipUrl. |
| GET | `/api/v1/usage` | Monthly quota and API export counts as JSON. |

Rate limit: 300 requests/hour per key · up to 5 active keys · exports count toward your plan quota. Agency plans receive export.complete / export.failed webhooks automatically.

## Export API FAQ

What developers ask before wiring it up.

### What can I build with the export API?

Client-onboarding automations, scheduled backups of no-code sites, migration tooling, and agency pipelines that turn a customer URL into a deployable ZIP without anyone opening the dashboard.

### Which plans include API access?

Pro and Agency. Create keys under Dashboard → Settings → Developer API. API exports count toward the same monthly export quota as dashboard exports.

### How do exports run?

Asynchronously. POST /api/v1/exports returns 202 with a jobId immediately; the job renders on real browser machines in the background. Poll the status URL every few seconds, or rely on completion webhooks on Agency.

### What are the limits?

300 requests per hour per key, up to 5 active keys per account, and your plan’s monthly export quota. Export ZIP retention follows your plan (30 days on Pro, unlimited on Agency).
