VISIMADE
← Developer Hub

Getting Started

  • Authentication
  • AI Coding Agents

Core APIs

Data APIs

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

Guides

Reference

Team Data API

Manage team data collections for pages with Team App storage. Includes CRUD operations and team file management.

Collection names must start with a lowercase letter and contain only lowercase letters, numbers, and underscores (regex: `^[a-z][a-z0-9_]*$`, max 100 characters). Examples: tasks, user_scores. Names starting with underscores or containing uppercase letters will return a 400 error.


Endpoints
GET

/api/pages/:id/team-data

List all collections

GET

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

List records in a collection

GET

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

Count records (with optional groupBy)

POST

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

Create a new record

GET

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

Get a single record

PATCH

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

Update a record

DELETE

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

Delete a record

Team File Endpoints

For file uploads and downloads within a team. Use these instead of the Page Assets API — team files support role-based permissions (member+ can upload, creator or admin+ can delete). In client-side code, use TeamData.uploadFile() etc. instead of calling these directly.

POST

/api/pages/:id/team-files

Upload a file (member+)

GET

/api/pages/:id/team-files

List files (viewer+)

GET

/api/pages/:id/team-files/:fileId?metadata=true

Get file metadata (viewer+)

GET

/api/pages/:id/team-files/:fileId

Download a file (viewer+)

DELETE

/api/pages/:id/team-files/:fileId

Delete a file (creator or admin+)


GET /api/pages/:id/team-data

List all collections available for a page. Requires team-data:read scope. Use this to discover what collections exist before querying them.

Request
curl -H "Authorization: Bearer vm_your_token_here" \
  https://visimade.com/api/pages/123/team-data
Response
{
  "collections": [
    {
      "name": "tasks",
      "recordCount": 18,
      "lastUpdated": "2024-01-15T10:30:00Z"
    },
    {
      "name": "stages",
      "recordCount": 8,
      "lastUpdated": "2024-01-14T15:20:00Z"
    }
  ]
}

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

List records in a team data collection. Requires team-data:read scope.

Query Parameters
ParameterTypeDescription
whereJSON stringFilter by data fields, e.g., {"status":"active"}
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
minebooleanOnly return records created by the authenticated user
beforenumberReturn records with ID less than this value (cursor pagination)
afternumberReturn records with ID greater than this value (cursor pagination)
Example
curl -H "Authorization: Bearer vm_your_token_here" \
  "https://visimade.com/api/pages/123/team-data/tasks?where=%7B%22status%22%3A%22active%22%7D&limit=10"
Response
{
  "records": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "collection": "tasks",
      "data": { "title": "Complete project", "status": "active", "priority": "high" },
      "createdBy": { "id": 42, "username": "johndoe" },
      "createdAt": "2024-01-15T10:30:00Z",
      "updatedAt": "2024-01-15T10:30:00Z"
    }
  ],
  "total": 25, "limit": 10, "offset": 0, "hasMore": true
}
Cursor-Based Pagination

For real-time collections like chat messages, use before and after instead of offset. Offset-based pagination can skip or duplicate records when new data is inserted. Cursors anchor to a specific record ID, so results are always consistent.

# Get the 20 most recent messages
curl -H "Authorization: Bearer ..." \
  "https://visimade.com/api/pages/123/team-data/messages?limit=20"

# Load older messages (use the smallest ID from previous results)
curl -H "Authorization: Bearer ..." \
  "https://visimade.com/api/pages/123/team-data/messages?limit=20&before=456"

# Poll for new messages (use the largest ID you already have)
curl -H "Authorization: Bearer ..." \
  "https://visimade.com/api/pages/123/team-data/messages?after=500&order=asc"

The response includes hasMore: true/false to indicate if more records exist beyond the current page. When using cursors, offset is ignored.


GET /api/pages/:id/team-data/:collection/count

Count records in a collection, optionally grouped by a data field. Requires team-data:read scope. Use this instead of fetching all records when you only need counts (e.g., reply counts, vote tallies).

Query Parameters
ParameterTypeDescription
whereJSON stringFilter by data fields, e.g., {"status":"active"}
minebooleanOnly count records created by the authenticated user
groupBystringGroup counts by this data field name
valuesstringComma-separated list of values to limit groupBy results (max 1000)
Simple Count
curl -H "Authorization: Bearer vm_your_token_here" \
  "https://visimade.com/api/pages/123/team-data/tasks/count?where=%7B%22status%22%3A%22active%22%7D"

// Response:
{ "count": 42 }
Grouped Count (countBy)

Get counts grouped by a data field — perfect for reply counts, vote tallies, category stats, etc. This replaces N separate API calls with a single request.

// Get reply counts for all messages in one request
curl -H "Authorization: Bearer vm_your_token_here" \
  "https://visimade.com/api/pages/123/team-data/replies/count?groupBy=parentId"

// Response:
{ "counts": { "msg-1": 5, "msg-2": 12, "msg-3": 0 } }

// Limit to specific parent IDs
curl -H "Authorization: Bearer vm_your_token_here" \
  "https://visimade.com/api/pages/123/team-data/replies/count?groupBy=parentId&values=msg-1,msg-2"

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

Create a new record in a collection. Requires team-data:write scope.

Request Body
{
  "data": { "title": "New task", "status": "pending", "priority": "medium" }
}
Example
curl -X POST \
  -H "Authorization: Bearer vm_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"data": {"title": "New task", "status": "pending"}}' \
  https://visimade.com/api/pages/123/team-data/tasks
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440001",
  "collection": "tasks",
  "data": { "title": "New task", "status": "pending" },
  "createdBy": { "id": 42, "username": "johndoe" },
  "createdAt": "2024-01-15T11:00:00Z",
  "updatedAt": "2024-01-15T11:00:00Z"
}

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

Update an existing record. Data is merged with existing values. Requires team-data:write scope. You can only update records you created, unless you are a team admin.

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

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

Delete a record. Requires team-data:write scope. You can only delete records you created, unless you are a team admin.

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

Batch Operations

Execute up to 100 create, update, and delete operations in a single request. The entire batch runs in one database transaction (all-or-nothing) and counts as a single rate limit hit.

POST

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

Execute batch operations (member+ for creates, owner/admin for others' records)

Request Body
{
  "operations": [
    { "op": "create", "data": { "title": "New item" } },
    { "op": "update", "id": "uuid-1", "data": { "order": 1 } },
    { "op": "update", "id": "uuid-2", "data": { "order": 2 } },
    { "op": "delete", "id": "uuid-3" }
  ]
}
Response
{
  "results": [
    { "op": "create", "success": true, "id": "uuid-new", "data": { "title": "New item" } },
    { "op": "update", "success": true, "id": "uuid-1" },
    { "op": "update", "success": true, "id": "uuid-2" },
    { "op": "delete", "success": true, "id": "uuid-3" }
  ]
}
Update = Shallow Merge (same as PATCH)

The update operation merges the provided data with the existing record's data. Only the fields you include are overwritten — fields you omit are preserved. For example, if a record has {"title": "Hello", "order": 3} and you send{"data": {"order": 1}}, the result is {"title": "Hello", "order": 1}. However, if you send a field with null, it will be set to null. This is a shallow merge — nested objects are fully replaced, not deep-merged.

Rules: Maximum 100 operations per batch. All operations run atomically — if any operation fails (e.g., record not found, permission denied), the entire batch is rolled back. Schema validation is applied to each create/update. Requires team-data:write scope.

Example (curl)
curl -X POST \\
  -H "Authorization: Bearer vm_your_token_here" \\
  -H "Content-Type: application/json" \\
  -d '{"operations": [
    {"op": "update", "id": "uuid-1", "data": {"order": 0}},
    {"op": "update", "id": "uuid-2", "data": {"order": 1}},
    {"op": "update", "id": "uuid-3", "data": {"order": 2}}
  ]}' \\
  https://visimade.com/api/pages/933/team-data/items/batch

On this page

  • Endpoints
  • Team File Endpoints
  • GET - List Collections
  • GET - List Records
  • GET - Count Records
  • POST - Create Record
  • PATCH - Update Record
  • DELETE - Delete Record
  • Batch Operations