VISIMADE
← Developer Hub

Getting Started

  • Agent Guide
  • Authentication
  • AI Coding Agents

Core APIs

Data APIs

  • Teams & Forking
  • Team Data API
  • Solo Data API
  • Social Data API
  • CMS Data API
  • Form Data API

Guides

Reference

Form Data API

Accept anonymous form submissions from visitors. No login required to submit. Only the page owner can read and manage submissions.

The Form Data API enables pages to collect data from anonymous visitors — email signups, contact forms, reservations, access requests, feedback, and more. Visitors submit without logging in. Only the page owner can view, update, and delete submissions.

Form vs CMS vs Social:

  • VisiForm — Anyone writes (no login), only owner reads. Use for: contact forms, waitlists, reservations.

  • CmsData — Only owner writes, everyone reads. Use for: blogs, catalogs, FAQs.

  • SocialData — Logged-in users write, everyone reads. Use for: comments, reviews, profiles.

Rate limiting: Anonymous submissions are rate-limited to 30 per minute per IP address per page to prevent abuse.


Overview
OperationAuth RequiredWho Can Do It
Submit (create)NoneAnyone (anonymous visitors)
List / ReadBearer token or sessionPage owner only
UpdateBearer token or sessionPage owner only
DeleteBearer token or sessionPage owner only
Get SchemaNoneAnyone (public)

Setup

Enable Form Data on a page by setting page_api_form_enabled to true:

curl -X PATCH \
  -H "Authorization: Bearer vm_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"page_api_form_enabled": true}' \
  https://visimade.com/api/pages/123

Endpoints
POST

/api/pages/:id/form-data/:collection

Submit a form entry (public, no auth)

GET

/api/pages/:id/form-data/:collection

List submissions (owner only)

GET

/api/pages/:id/form-data/:collection/:recordId

Get a single submission (owner only)

PATCH

/api/pages/:id/form-data/:collection/:recordId

Update a submission (owner only)

DELETE

/api/pages/:id/form-data/:collection/:recordId

Delete a submission (owner only)

POST

/api/pages/:id/form-data/:collection/batch

Batch operations (owner only)

GET

/api/pages/:id/form-data/:collection/count

Count submissions (owner only)

GET

/api/pages/:id/form-data/:collection/schema

Get collection schema (public)

PUT

/api/pages/:id/form-data/:collection/schema

Set collection schema (owner only)


POST /api/pages/:id/form-data/:collection

Submit a form entry. No authentication required. Rate limited to 30 requests per minute per IP. If a schema is defined for the collection, the data will be validated against it.

Request Body
FieldTypeDescription
dataobject (required)The form submission data as a JSON object
Example
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"data": {"email": "user@example.com", "name": "Jane Doe"}}' \
  https://visimade.com/api/pages/123/form-data/waitlist
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "collection": "waitlist",
  "data": { "email": "user@example.com", "name": "Jane Doe" },
  "createdAt": "2026-03-25T10:30:00Z"
}

GET /api/pages/:id/form-data/:collection

List submissions in a collection. Page owner only. Requires form-data:read scope.

Query Parameters
ParameterTypeDescription
whereJSON stringFilter by data fields, e.g., {"status":"pending"}
orderBystringSort field: created_at or updated_at
orderstringasc or desc (default)
limitnumberMax records to return (default 50, max 100)
offsetnumberNumber of records to skip for pagination
Example
curl -H "Authorization: Bearer vm_your_token_here" \
  "https://visimade.com/api/pages/123/form-data/waitlist?limit=10&order=desc"
Response
{
  "records": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "collection": "waitlist",
      "data": { "email": "user@example.com", "name": "Jane Doe" },
      "createdAt": "2026-03-25T10:30:00Z",
      "updatedAt": "2026-03-25T10:30:00Z"
    }
  ],
  "total": 42, "limit": 10, "offset": 0, "hasMore": true
}

PATCH /api/pages/:id/form-data/:collection/:recordId

Update a submission. Data is merged (not replaced). Page owner only.Requires form-data:write scope. Useful for adding status fields (e.g., marking a submission as "approved").

curl -X PATCH \
  -H "Authorization: Bearer vm_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"data": {"status": "approved"}}' \
  https://visimade.com/api/pages/123/form-data/waitlist/550e8400-e29b-41d4-a716-446655440000

DELETE /api/pages/:id/form-data/:collection/:recordId

Delete a submission. Page owner only.Requires form-data:write scope. Returns 204 on success.

curl -X DELETE \
  -H "Authorization: Bearer vm_your_token_here" \
  https://visimade.com/api/pages/123/form-data/waitlist/550e8400-e29b-41d4-a716-446655440000

Batch Operations

Execute up to 100 operations in a single request. Page owner only (except batches containing only create operations, which are public like individual submissions).

POST

/api/pages/:id/form-data/:collection/batch

Execute batch operations

{
  "operations": [
    { "op": "create", "data": { "email": "new@example.com" } },
    { "op": "update", "id": "uuid-1", "data": { "status": "approved" } },
    { "op": "delete", "id": "uuid-2" }
  ]
}

Client-Side SDK (VisiForm)

When Form Data is enabled, window.VisiForm is automatically injected into your page. Do NOT include any script tags for it.

For Anyone (no login required)
await VisiForm.ready;

// Submit a form entry
const result = await VisiForm.submit('waitlist', {
  email: 'user@example.com',
  name: 'Jane Doe'
});

// Get collection schema (for building dynamic forms)
const schema = await VisiForm.getSchema('waitlist');
For Page Owner Only
await VisiForm.ready;

// List submissions
const { records, total } = await VisiForm.find('waitlist', { order: 'desc', limit: 50 });

// Get single submission
const record = await VisiForm.findOne('waitlist', recordId);

// Update a submission (merge data)
await VisiForm.update('waitlist', recordId, { status: 'approved' });

// Delete a submission
await VisiForm.delete('waitlist', recordId);

// Count submissions
const { count } = await VisiForm.count('waitlist');

// Check identity
VisiForm.isOwner();         // true if page owner
VisiForm.isAuthenticated(); // true if logged in
Example: Waitlist Signup Page
await VisiForm.ready;

// Visitor-facing form
document.getElementById('signup-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  await VisiForm.submit('waitlist', {
    email: document.getElementById('email').value,
    name: document.getElementById('name').value
  });
  document.getElementById('signup-form').innerHTML = '<p>Thanks! We\'ll be in touch.</p>';
});

// Owner-only admin panel
if (VisiForm.isOwner()) {
  document.getElementById('admin').style.display = 'block';
  const { records, total } = await VisiForm.find('waitlist', { order: 'desc' });
  document.getElementById('count').textContent = total + ' signups';
  // render submissions list...
}

On this page

  • Overview
  • Setup
  • Endpoints
  • POST - Submit (Public)
  • GET - List Submissions
  • PATCH - Update Submission
  • DELETE - Delete Submission
  • Batch Operations
  • Client-Side SDK (VisiForm)