Forms API
A Form exposes a template (or Template Set) as a public, shareable URL like https://automette.com/forms/{slug}. Each submission becomes a render. You can manage forms in the dashboard, or via the API for provisioning at scale.
The hosted form is at /forms/{slug} and submissions fire the form.submitted webhook event.
Create a form
POST /api/v1/forms
Authorization: Bearer dg_your_api_key
Content-Type: application/jsonRequest body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Human label for the form. Shown in the dashboard. |
template_id | string | one of | Render this single template per submission. |
template_set_id | string | one of | Render every template in this Set per submission. Cannot combine with template_id. |
render_mode | string | no | "sync" (default — submitter sees the file inline) or "async" (submitter gets a thank-you, file delivered via webhook). |
config | array | no | Field definitions. See below. |
max_renders | integer | no | Cap on lifetime submissions. null = unlimited. |
expires_at | string | no | ISO date; form auto-disables after this. |
requires_password | boolean | no | Gate the form with a password. |
password | string | no | Required when requires_password: true. Stored as SHA-256 hash. |
Field config
Each entry in config describes one input on the rendered form:
{
"key": "price",
"label": "Listing Price",
"placeholder": "$2,450,000",
"required": true,
"hidden": false,
"default": ""
}Hidden fields are not shown to the submitter but are still passed to the renderer — useful for tagging submissions with a source code.
Response — 201
{
"id": "cm4frm3xz0001jw04y7c4m1gh",
"slug": "property-listing-form",
"name": "Property Listing Form",
"url": "https://automette.com/forms/property-listing-form",
"template_id": "cm4tpl8e20001js04xq2v9k3m",
"template_set_id": null,
"render_mode": "sync",
"status": "active",
"render_count": 0,
"max_renders": 100,
"expires_at": "2026-12-31T00:00:00.000Z",
"requires_password": false,
"created_at": "2026-04-22T12:00:00.000Z",
"updated_at": "2026-04-22T12:00:00.000Z"
}Errors
| Code | When |
|---|---|
400 | Missing name, missing both template_id and template_set_id, supplied both, or requires_password without password |
401 | Missing or invalid API key |
404 | Referenced template or set not in your team |
List forms
GET /api/v1/forms
Authorization: Bearer dg_your_api_keyReturns an array of the same shape as the create response, ordered by most recently created.
Get a form
GET /api/v1/forms/{id}
Authorization: Bearer dg_your_api_keySame as one element of the list response, plus the full config array.
Update a form
PATCH /api/v1/forms/{id}
Authorization: Bearer dg_your_api_key
Content-Type: application/jsonAll fields optional. Send only what you want to change. template_id and template_set_id cannot be changed after creation — delete and recreate the form to switch.
Set status: "disabled" to pause submissions without deleting the form. The hosted URL returns a friendly "form is no longer accepting submissions" page.
Delete a form
DELETE /api/v1/forms/{id}
Authorization: Bearer dg_your_api_keyReturns 204 No Content. The hosted URL stops working immediately.
Example — provision a one-shot form
curl -X POST https://automette.com/api/v1/forms \
-H "Authorization: Bearer dg_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Spring Promo Certificate",
"template_id": "cm4tpl8e20001js04xq2v9k3m",
"max_renders": 1,
"expires_at": "2026-05-31",
"config": [
{ "key": "name", "label": "Recipient name", "required": true }
]
}'