Dashboard
How it Works Documentation Quick Start PAPI — Pages & Assets MAPI — Dynamic Data Integrations SAPI — Sessions & Forms MCP Server OpenClaw Skill Tools Deploy Dashboard

MAPI Documentation

The Meta API (MAPI) lets you create dynamic data structures (entities) and manage records programmatically. Think of it as a runtime database builder — define your schema via API, and MAPI creates the tables and CRUD endpoints automatically.

ℹ️ When to use MAPI Use MAPI when you need structured data like blog posts, products, team members, or any content that might be used across multiple pages. PAPI handles the presentation, MAPI handles the data.

Authentication

MAPI uses Bearer token authentication. Entity management operations (creating, updating, deleting entities) also require an X-Project-ID header. Record operations include the project ID in the URL path instead.

# Entity management (meta operations)
Authorization: Bearer {your_api_token}
X-Project-ID: {your_project_id}

# Record operations (project ID in URL)
Authorization: Bearer {your_api_token}
⚠️ Token-Project Binding Each API token is bound to a specific project. You cannot use a token from project A to access data in project B. Validate your token with GET /mapi/debug/check-key.

Base URL

https://api.websitepublisher.ai/mapi

All MAPI endpoints use the /mapi prefix. The full API gateway also provides:

APIBase PathPurpose
PAPI/papi/*Pages, assets, fragments, publishing
MAPI/mapi/*Dynamic data structures & records
SAPI/sapi/*Sessions, forms, visitor auth
IAPI/iapi/*Integrations (email, payments, etc.)

Entities

Entities are like database tables. You define the structure, MAPI creates the table and all CRUD routes automatically.

GET /mapi/entities

List all entities in the project. Returns name, plural, property definitions, and public_read status for each entity.

Headers: Authorization, X-Project-ID

POST /mapi/entities

Create a new entity with properties. Optionally enable public read access at creation time.

Request Body

{
    "name": "blogpost",
    "plural": "blogposts",
    "description": "Blog articles with publish status",
    "public_read": false,
    "properties": [
        {"name": "title", "type": "varchar", "length": 200, "required": true},
        {"name": "content", "type": "text", "required": true},
        {"name": "published", "type": "tinyint", "default": 0},
        {"name": "published_at", "type": "datetime"}
    ]
}
FieldTypeRequiredDescription
namestringYesSingular entity name (e.g. blogpost)
pluralstringYesPlural form (e.g. blogposts)
descriptionstringNoHuman-readable description
public_readbooleanNoEnable public read-only access (default: false)
propertiesarrayYesArray of property definitions
GET /mapi/entities/{name}/schema

Get the OpenAPI schema for a specific entity, including all property definitions and their types.

Headers: Authorization, X-Project-ID

DELETE /mapi/entities/{name}

Delete an entity and all its records.

⚠️ Destructive Action This permanently deletes the entity table and ALL its data. This cannot be undone.

Update Entity

Update entity metadata such as the plural name, description, or public_read access flag.

PUT /mapi/entities/{name}

Update entity metadata. Use this to toggle public_read access or change the description.

Request Body

{
    "public_read": true,
    "description": "Portfolio showcase items visible to the public"
}
FieldTypeDescription
public_readbooleanEnable/disable public read-only access
descriptionstringUpdated description
pluralstringUpdated plural name

Response

{
    "success": true,
    "data": {
        "name": "showcase",
        "plural": "showcases",
        "public_read": true,
        "properties": [...]
    }
}

Properties

Properties define the fields (columns) of your entity. You can add properties at entity creation or afterwards.

POST /mapi/entities/{name}/properties

Add a new property to an existing entity.

{
    "name": "author",
    "type": "varchar",
    "length": 100
}
DELETE /mapi/entities/{name}/properties/{property_id}

Remove a property from an entity.

⚠️ Use Property ID This endpoint requires the numeric property ID, not the property name. Get the ID from the entity schema endpoint.

Property Types

Each property has a type that determines how data is stored and validated.

TypeDescriptionParameters
varcharShort text stringlength (max 255, default 255)
textLong text content (unlimited)None
intInteger numberNone
tinyintSmall integer (0–255), commonly used as boolean (0/1)None
datetimeDate and timeFormat: YYYY-MM-DD HH:MM:SS
⚠️ Not Supported float, decimal, double, and boolean are not supported as property types. Use tinyint for boolean values (0/1) and varchar or int for numeric data.

Property Definition Fields

FieldTypeRequiredDescription
namestringYesProperty name (see naming rules)
typestringYesOne of the types listed above
lengthintegerNoMax length for varchar (default: 255)
requiredbooleanNoWhether the field is required (default: false)
defaultmixedNoDefault value for the property

Naming Rules

Entity Names

Entity names must match the following pattern:

/^[a-zA-Z_][a-zA-Z0-9_]*$/
RuleValidInvalid
Must start with letter or underscoreblogpost, _temp123post
Letters, digits, underscores onlypost_v2, Item1my-post, post.item
Case-insensitive uniquenessBlogPost and blogpost are treated as the same name

Property Names

Property names follow the same rules as entity names, but the following names are reserved and cannot be used:

Reserved NameReason
idAuto-generated primary key
created_atAuto-generated timestamp
updated_atAuto-generated timestamp
creatorInternal system field
hashtokenInternal system field

Records (CRUD)

Once you've created an entity, you can create, read, update, and delete records. The project ID is part of the URL path for all record operations.

GET /mapi/project/{project_id}/{entity}

List all records with optional pagination and sorting. See Pagination for query parameters.

POST /mapi/project/{project_id}/{entity}

Create a new record.

{
    "title": "My First Blog Post",
    "content": "This is the content...",
    "published": 1,
    "published_at": "2026-01-13 10:00:00"
}
GET /mapi/project/{project_id}/{entity}/{record_id}

Get a specific record by ID.

PUT /mapi/project/{project_id}/{entity}/{record_id}

Update an existing record. Send only the fields you want to change.

{
    "published": 1,
    "published_at": "2026-05-01 12:00:00"
}
DELETE /mapi/project/{project_id}/{entity}/{record_id}

Delete a record permanently.

GET /mapi/project/{project_id}/{entity}/count

Get the total number of records in the entity.

Pagination

Use query parameters on the list records endpoint to control pagination and sorting:

ParameterTypeDefaultDescription
limitinteger50Number of records per page (max: 100)
offsetinteger0Number of records to skip
# Get records 11-20
GET /mapi/project/{id}/{entity}?limit=10&offset=10
ℹ️ MCP Tool Pagination When using MAPI through the MCP tools, pagination uses page and per_page parameters instead. The MCP layer translates these to limit/offset for you. You can also use sort_by and sort_order (ASC/DESC) via MCP tools.
POST /mapi/project/{project_id}/{entity}/search

Search records with key-value filters. Returns all records matching the filter criteria.

{
    "filters": {
        "published": 1,
        "author": "Jane"
    }
}

Filters use exact match. Multiple filters are combined with AND logic.

Bulk Operations

Perform multiple create, update, or delete operations in a single request for better performance.

POST /mapi/project/{project_id}/{entity}/bulk

Create multiple records at once.

{
    "records": [
        {"title": "Post One", "published": 1},
        {"title": "Post Two", "published": 0},
        {"title": "Post Three", "published": 1}
    ]
}
PUT /mapi/project/{project_id}/{entity}/bulk

Update multiple records at once. Each record must include its id.

{
    "records": [
        {"id": 1, "published": 1},
        {"id": 2, "published": 1}
    ]
}
DELETE /mapi/project/{project_id}/{entity}/bulk

Delete multiple records by ID.

{
    "ids": [1, 2, 3]
}

Public Read Access

Entities with public_read enabled expose read-only endpoints that require no authentication. This is useful for loading data directly from client-side JavaScript — for example, displaying a portfolio, product catalog, or blog on your website.

✅ How it works Enable public_read on an entity via POST /mapi/entities (at creation) or PUT /mapi/entities/{name} (afterwards). Three read-only endpoints become available without authentication.
GET /mapi/public/project/{project_id}/{entity}

List records from a public entity. No authentication required. Supports limit (max 100) and offset query parameters. Internal fields (creator, hashtoken) are automatically stripped from the response.

Response

{
    "success": true,
    "data": [
        {"id": 1, "title": "Project Alpha", "created_at": "..."},
        {"id": 2, "title": "Project Beta", "created_at": "..."}
    ],
    "pagination": {
        "limit": 50,
        "offset": 0,
        "total": 2
    }
}
GET /mapi/public/project/{project_id}/{entity}/{record_id}

Get a single record from a public entity. No authentication required.

GET /mapi/public/project/{project_id}/{entity}/count

Count records in a public entity. No authentication required.

ℹ️ Security Notes Public endpoints only support GET requests — create, update, and delete always require authentication. Entity schemas and property definitions are never exposed through public routes. Public routes have stricter rate limiting than authenticated routes.

Client-side JavaScript Example

// Fetch public data directly from the browser — no API key needed
const response = await fetch(
    'https://api.websitepublisher.ai/mapi/public/project/22254/showcase'
);
const { data } = await response.json();

data.forEach(item => {
    console.log(item.title, item.description);
});

Complete Example

Building a product catalog with public access:

# 1. Create the product entity with public read enabled
curl -X POST "https://api.websitepublisher.ai/mapi/entities" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Project-ID: {project_id}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "product",
    "plural": "products",
    "public_read": true,
    "properties": [
      {"name": "title", "type": "varchar", "length": 200, "required": true},
      {"name": "slug", "type": "varchar", "length": 100, "required": true},
      {"name": "description", "type": "text"},
      {"name": "price", "type": "int"},
      {"name": "in_stock", "type": "tinyint", "default": 1}
    ]
  }'

# 2. Add a product
curl -X POST "https://api.websitepublisher.ai/mapi/project/{project_id}/product" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Wireless Keyboard",
    "slug": "wireless-keyboard",
    "description": "Ergonomic wireless keyboard with backlight",
    "price": 4999,
    "in_stock": 1
  }'

# 3. Add more products in bulk
curl -X POST "https://api.websitepublisher.ai/mapi/project/{project_id}/product/bulk" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [
      {"title": "USB-C Hub", "slug": "usb-c-hub", "price": 2999, "in_stock": 1},
      {"title": "Monitor Stand", "slug": "monitor-stand", "price": 3499, "in_stock": 0}
    ]
  }'

# 4. List in-stock products (authenticated)
curl -X POST "https://api.websitepublisher.ai/mapi/project/{project_id}/product/search" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"filters": {"in_stock": 1}}'

# 5. Fetch products publicly (no auth needed — public_read is on)
curl "https://api.websitepublisher.ai/mapi/public/project/{project_id}/product?limit=10"

Powered by WebSumo