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
| Operation | Auth Required | Who Can Do It |
|---|---|---|
| Submit (create) | None | Anyone (anonymous visitors) |
| List / Read | Bearer token or session | Page owner only |
| Update | Bearer token or session | Page owner only |
| Delete | Bearer token or session | Page owner only |
| Get Schema | None | Anyone (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/123Endpoints
/api/pages/:id/form-data/:collection
Submit a form entry (public, no auth)
/api/pages/:id/form-data/:collection
List submissions (owner only)
/api/pages/:id/form-data/:collection/:recordId
Get a single submission (owner only)
/api/pages/:id/form-data/:collection/:recordId
Update a submission (owner only)
/api/pages/:id/form-data/:collection/:recordId
Delete a submission (owner only)
/api/pages/:id/form-data/:collection/batch
Batch operations (owner only)
/api/pages/:id/form-data/:collection/count
Count submissions (owner only)
/api/pages/:id/form-data/:collection/schema
Get collection schema (public)
/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
| Field | Type | Description |
|---|---|---|
data | object (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/waitlistResponse
{
"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
| Parameter | Type | Description |
|---|---|---|
where | JSON string | Filter by data fields, e.g., {"status":"pending"} |
orderBy | string | Sort field: created_at or updated_at |
order | string | asc or desc (default) |
limit | number | Max records to return (default 50, max 100) |
offset | number | Number 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-446655440000DELETE /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).
/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 inExample: 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)