The formdata.dev API has two surfaces:
| Surface | Base URL | Auth | Purpose |
|---|---|---|---|
| Ingestion | POST /v1/f/:publicKey |
None (public key in URL) | Accept form submissions |
| Admin | /v1/admin/* |
x-tenant-key header |
Manage accounts, forms, destinations, keys |
Or, if you created a subdomain during account setup:
All admin endpoints (except account creation) require a tenant key passed in the x-tenant-key header:
The ingestion endpoint requires no authentication — the public key in the URL path identifies the form.
Every response returns JSON with an ok boolean:
Success:
Error:
Validation errors return a Zod flatten() structure:
| Code | Meaning |
|---|---|
200 |
Success (reads, updates, deletes) |
202 |
Accepted (submission queued for async delivery) |
400 |
Invalid JSON or validation error |
401 |
Missing or invalid x-tenant-key |
403 |
Origin not allowed (ingestion CORS) |
404 |
Resource not found or form disabled |
409 |
Conflict (e.g. slug already taken) |
413 |
Payload too large (max 128 KB) |
| Method | Path | Description |
|---|---|---|
POST |
/v1/f/:publicKey |
Submit form data |
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/v1/admin/accounts |
None | Create account + tenant key |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v1/admin/forms |
x-tenant-key |
List all forms |
POST |
/v1/admin/forms |
x-tenant-key |
Create a form |
GET |
/v1/admin/forms/:id |
x-tenant-key |
Get form + destinations |
PUT |
/v1/admin/forms/:id |
x-tenant-key |
Update a form |
DELETE |
/v1/admin/forms/:id |
x-tenant-key |
Delete a form |
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/v1/admin/forms/:id/destinations |
x-tenant-key |
Add destination to form |
DELETE |
/v1/admin/forms/:id/destinations/:destId |
x-tenant-key |
Remove destination |
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/v1/admin/keys/rotate |
x-tenant-key |
Rotate tenant key |