Form Builder / API Documentation
← Back to app

API Reference

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

Authentication

All form and instance endpoints require an APP_SID cookie. Obtain it via OAuth login or by POSTing a token directly.

GET /api/auth/check Check session

Returns whether the current session is authenticated. No auth cookie required.

Response

{ "authenticated": true }
POST /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 }
DELETE /api/token Clear session

Clears the APP_SID cookie, logging the user out.

Response

{ "success": true }
GET /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

Instances

Fetch the Zesty instances accessible to the authenticated user. Requires APP_SID cookie.

GET /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

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.

GET /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

ParameterDescription
instanceZuidThe 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"
    }
  ]
}
POST /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

typeExtra FieldsNotes
inputlabel, name, placeholder, required, inputTypeinputType: text (default), email, tel, url, number
textarealabel, name, placeholder, requiredMulti-line text area
selectlabel, name, placeholder, required, optionsoptions: comma-separated string
hiddenname, valueNot visible in rendered form
submitlabelSubmit 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"
  }
}

Publish

Publishing makes a form view live on the Zesty instance.

POST /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

ParameterDescription
instanceZuidInstance ZUID
viewZuidView 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"

Changelog

Returns the app update log. No authentication required.

GET /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"
    },
    ...
  ]
}

How Forms Are Stored

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.