The Form Builder exposes a REST API used by the frontend. All endpoints are prefixed with /api. Authentication uses a cookie named APP_SID set via OAuth or the token endpoint.
Base URL
https://your-domain.com/api
All form and instance endpoints require an APP_SID cookie. Obtain it via OAuth login or by POSTing a token directly.
/api/auth/check
Check session
Returns whether the current session is authenticated. No auth cookie required.
Response
{ "authenticated": true }
/api/token
Set APP_SID token
Stores the provided Zesty APP_SID as an HTTP-only cookie (7-day expiry).
Request Body
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response
{ "success": true }
/api/token
Clear session
Clears the APP_SID cookie, logging the user out.
Response
{ "success": true }
/api/auth/:provider/login
OAuth redirect
Redirects the browser to the Zesty OAuth provider. Supported providers: google, azure, github. After authentication, Zesty redirects back to /api/auth/callback which sets the cookie.
Examples
GET /api/auth/google/login GET /api/auth/azure/login GET /api/auth/github/login
Fetch the Zesty instances accessible to the authenticated user. Requires APP_SID cookie.
/api/instances
List all instances
Returns all Zesty instances the authenticated user has access to. The Zesty accounts API returns the full list in a single response.
Response
{
"data": [
{
"ZUID": "8-abc123-def456",
"name": "My Website",
"domain": "mywebsite.com",
"createdAt": "2024-01-15T12:00:00Z"
},
...
]
}
Errors
401 { "error": "Missing APP_SID token" }
500 { "error": "Zesty API error 500: ..." }
Forms are stored as Zesty views at /forms/*.html. Each view contains a var defined = {...} JSON block with the form configuration, followed by the rendered HTML.
/api/instances/:instanceZuid/forms
List forms
Returns all forms saved to the given instance. Scans all Zesty views matching the pattern /forms/*.html with status dev and parses the embedded config.
URL Parameters
| Parameter | Description |
|---|---|
| instanceZuid | The Zesty instance ZUID (e.g. 8-abc123-def456) |
Response
{
"data": [
{
"name": "Contact Form",
"slug": "contact-form",
"fields": [
{ "id": "f1", "type": "input", "label": "Full Name", "name": "full_name", "required": true },
{ "id": "f2", "type": "input", "label": "Email", "name": "email", "inputType": "email", "required": true },
{ "id": "f3", "type": "submit", "label": "Send" }
],
"viewZuid": "11-xyz-789",
"instanceZuid": "8-abc123-def456",
"fileName": "/forms/contact-form.html"
}
]
}
/api/instances/:instanceZuid/forms
Create or update a form
Creates or updates a form. If viewZuid is provided, updates that view. Otherwise, checks for an existing view at /forms/{slug}.html and updates it, or creates a new one. The stored view contains the JSON config in a <script> tag followed by rendered HTML.
Request Body
{
"name": "Contact Form",
"fields": [
{ "id": "f1", "type": "input", "label": "Full Name", "name": "full_name", "required": true, "placeholder": "Jane Doe" },
{ "id": "f2", "type": "input", "label": "Email", "name": "email", "inputType": "email", "required": true },
{ "id": "f3", "type": "textarea", "label": "Message", "name": "message" },
{ "id": "f4", "type": "select", "label": "Topic", "name": "topic", "options": "Sales,Support,Other" },
{ "id": "f5", "type": "hidden", "name": "source", "value": "website" },
{ "id": "f6", "type": "submit", "label": "Send Message" }
],
"viewZuid": "11-xyz-789"
}
Field Types
| type | Extra Fields | Notes |
|---|---|---|
| input | label, name, placeholder, required, inputType | inputType: text (default), email, tel, url, number |
| textarea | label, name, placeholder, required | Multi-line text area |
| select | label, name, placeholder, required, options | options: comma-separated string |
| hidden | name, value | Not visible in rendered form |
| submit | label | Submit button |
Response
{
"data": {
"viewZuid": "11-xyz-789",
"instanceZuid": "8-abc123-def456",
"fileName": "/forms/contact-form.html",
"name": "Contact Form",
"slug": "contact-form",
"fields": [...],
"message": "Saved to /forms/contact-form.html"
}
}
Publishing makes a form view live on the Zesty instance.
/api/instances/:instanceZuid/forms/:viewZuid/publish
Publish a form
Publishes the latest version of a form view. Internally fetches the current version number from Zesty, then publishes that version.
URL Parameters
| Parameter | Description |
|---|---|
| instanceZuid | Instance ZUID |
| viewZuid | View ZUID returned from the save endpoint |
Response
{ "data": { "viewZuid": "11-xyz-789", "message": "Published" } }
Example — Save then Publish
# 1. Save the form
curl -X POST https://your-domain.com/api/instances/8-abc123-def456/forms \
-H "Content-Type: application/json" \
-b "APP_SID=your_token_here" \
-d '{
"name": "Newsletter Signup",
"fields": [
{ "id": "f1", "type": "input", "label": "Email", "name": "email", "inputType": "email", "required": true },
{ "id": "f2", "type": "submit", "label": "Subscribe" }
]
}'
# 2. Publish using the viewZuid from the save response
curl -X POST https://your-domain.com/api/instances/8-abc123-def456/forms/11-xyz-789/publish \
-b "APP_SID=your_token_here"
Returns the app update log. No authentication required.
/api/changelog
App changelog
Returns entries from the update_log.json file, newest first.
Response
{
"data": [
{
"timestamp": "2026-03-10T20:30:00Z",
"update": "Added dropdown (select) field type"
},
...
]
}
Each form is stored as a Zesty view file at /forms/{slug}.html. The file contains a JSON config block followed by complete styled HTML:
<script>
var defined = {
"name": "Contact Form",
"slug": "contact-form",
"fields": [
{ "id": "f1", "type": "input", "label": "Full Name", "name": "full_name", "required": true },
{ "id": "f2", "type": "submit", "label": "Send" }
]
};
</script>
<style>
.form-container { max-width: 600px; margin: 0 auto; ... }
...
</style>
<div class="form-container">
<h1>Contact Form</h1>
<form>
<div class="form-group">
<label for="full_name">Full Name *</label>
<input type="text" id="full_name" name="full_name" required />
</div>
<div class="form-group">
<button type="submit" class="btn-submit">Send</button>
</div>
</form>
</div>
The JSON config is parsed on load using the regex /var\s+defined\s*=\s*(\{[\s\S]*?\});/ to reconstruct the form editor state.