33 KiB
API Reference - E2E Documentation
Overview
The Tour Builder Platform exposes a RESTful API built with Express.js. All endpoints follow consistent patterns for CRUD operations, authentication, and response formats.
Base URL: http://localhost:3000/api for local development.
Standard VM: Apache serves the public domain on port 80, the frontend
PM2 app listens on 3001, and the backend PM2 app listens on 3000 with
NODE_ENV=dev_stage. Use http://127.0.0.1:3000/api/... for direct VM backend
checks, or http://tbp.flatlogic.app/api/... through Apache/Cloudflare. See
deployment-vm.md.
Authentication
JWT Bearer Token
Most endpoints require JWT authentication via the Authorization header:
Authorization: Bearer <token>
Token Details:
- Expiration: 6 hours
- Payload:
{ id, email, name } - Obtained via
/api/auth/signin/localor OAuth callbacks
Public Endpoints (No Auth Required)
GET /api/healthPOST /api/auth/signin/localPOST /api/auth/send-password-reset-emailPUT /api/auth/password-resetPUT /api/auth/verify-emailGET /api/auth/email-configuredGET /api/auth/signin/googleGET /api/auth/signin/microsoftGET /api/runtime-context
Runtime Public Access
In production runtime mode only, certain GET endpoints allow unauthenticated read access (stage requires authentication):
GET /api/projectsGET /api/tour_pagesGET /api/project_audio_tracksGET /api/global-ui-control-defaultsGET /api/project-ui-control-settings/project/:projectId/env/production
Note: The X-Runtime-Environment header must be set to production for public access. Stage environment (stage) requires JWT authentication as it serves as a workspace for review.
Standard Response Formats
Success Responses
Single Entity:
{
"id": "uuid-here",
"name": "Entity Name",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
List Response:
{
"rows": [
{ "id": "uuid-1", "name": "Entity 1" },
{ "id": "uuid-2", "name": "Entity 2" }
],
"count": 100
}
Count Response:
{
"count": 100
}
Error Responses
{
"error": "Error message description"
}
HTTP Status Codes:
| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request (validation errors) |
| 401 | Unauthorized (missing/invalid token) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found |
| 429 | Too Many Requests (rate limited) |
| 500 | Internal Server Error |
Rate Limiting
The API uses rate limiting to prevent abuse. Rate limits are applied per IP address, and rate limit headers are returned with each response:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests allowed per window |
X-RateLimit-Remaining |
Remaining requests in current window |
X-RateLimit-Reset |
ISO timestamp when the window resets |
Retry-After |
Seconds until you can retry (when limited) |
Rate Limit Configuration
| Limiter | Window | Max Requests | Endpoints |
|---|---|---|---|
| Auth | 15 minutes | 10 | /api/auth/signin/* |
| Password Reset | 1 hour | 5 | /api/auth/send-password-reset-email |
| API | 1 minute | 100 | General API endpoints |
| Upload | 1 minute | 10 | /api/file/upload* |
| Download | 1 minute | 200 | /api/file/download, /api/file/presign |
| Search | 1 minute | 30 | /api/search |
Note: Rate limiting is skipped for localhost (127.0.0.1, ::1) in development mode.
Standard Entity Endpoints
All entity routes (projects, assets, users, etc.) support these standard endpoints:
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/{entity} |
List entities (paginated) |
GET |
/api/{entity}/count |
Get count only |
GET |
/api/{entity}/autocomplete |
Autocomplete search |
GET |
/api/{entity}/:id |
Get single entity by ID |
POST |
/api/{entity} |
Create entity |
PUT |
/api/{entity}/:id |
Update entity |
DELETE |
/api/{entity}/:id |
Delete entity |
POST |
/api/{entity}/deleteByIds |
Bulk delete |
POST |
/api/{entity}/bulk-import |
CSV import |
GET /api/{entity}/count
Get count of entities matching the query.
Query Parameters: Same as list endpoint
Response:
{
"count": 100
}
GET /api/{entity}/autocomplete
Get autocomplete suggestions for a field.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
query |
string | Search query |
limit |
number | Max results (default: 10) |
offset |
number | Pagination offset |
Response:
[
{ "id": "uuid-1", "label": "Option 1" },
{ "id": "uuid-2", "label": "Option 2" }
]
Standard Query Parameters
All list endpoints support these query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
number | 10 | Items per page |
offset |
number | 0 | Pagination offset |
page |
number | 0 | Page number (alternative to offset) |
search |
string | - | Text search across searchable fields |
sort |
string | - | Sort field (e.g., name or name:DESC) |
filetype |
string | - | Export format (csv) |
Entity-Specific Filters
Filters vary by entity based on their SEARCHABLE_FIELDS, RANGE_FIELDS, and ENUM_FIELDS:
# Text search
?search=keyword
# Range filters (numeric/date)
?createdAtRange=2024-01-01,2024-12-31
?sizeRange=0,1000000
# Enum/exact match filters
?type=image
?status=active
?environment=production
# Relationship filters
?projectId=uuid
?tour_pageId=uuid
Authentication Endpoints
POST /api/auth/signin/local
Login with email and password.
Rate Limit: 10 requests per 15 minutes
Request:
{
"email": "user@example.com",
"password": "password123"
}
Response:
{
"id": "user-uuid",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
Self-Registration
Self-registration is disabled. The API does not expose
POST /api/auth/signup; new users are created through the authenticated Users
flow and receive an invitation/setup link.
GET /api/auth/me
Get current authenticated user.
Auth: Required
Response:
{
"id": "user-uuid",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"app_role": {
"id": "role-uuid",
"name": "Admin"
}
}
PUT /api/auth/password-update
Update password for authenticated user.
Auth: Required
Request:
{
"currentPassword": "oldpassword",
"newPassword": "newpassword123"
}
POST /api/auth/send-password-reset-email
Send password reset email.
Rate Limit: 5 requests per hour
Request:
{
"email": "user@example.com"
}
POST /api/auth/send-email-address-verification-email
Resend email verification email for current user.
Auth: Required
Response: true on success
PUT /api/auth/password-reset
Reset password with token.
Request:
{
"token": "reset-token-from-email",
"password": "newpassword123"
}
PUT /api/auth/profile
Update user profile.
Auth: Required
Request:
{
"profile": {
"firstName": "John",
"lastName": "Doe",
"phoneNumber": "+1234567890"
}
}
OAuth Endpoints
| Endpoint | Description |
|---|---|
GET /api/auth/signin/google |
Initiate Google OAuth |
GET /api/auth/signin/google/callback |
Google OAuth callback |
GET /api/auth/signin/microsoft |
Initiate Microsoft OAuth |
GET /api/auth/signin/microsoft/callback |
Microsoft OAuth callback |
System Endpoints
GET /api/health
Health check endpoint.
Auth: Not required
Response:
{
"status": "ok",
"timestamp": "2024-01-01T00:00:00.000Z",
"uptime": 3600,
"environment": "production",
"database": "connected"
}
GET /api/runtime-context
Get runtime context information.
Auth: Not required
Response:
{
"mode": "admin",
"projectSlug": null
}
Modes:
admin- Full access (localhost or admin subdomain)stage- Stage environment (stage.{project}.domain)production- Production environment ({project}.domain)
File Endpoints
POST /api/file/upload-sessions/init
Initialize chunked upload session.
Auth: Required
Request:
{
"filename": "video.mp4",
"size": 104857600,
"mimeType": "video/mp4",
"projectId": "project-uuid"
}
Response:
{
"sessionId": "session-uuid",
"chunkSize": 5242880,
"totalChunks": 20,
"expiresAt": "2024-01-02T00:00:00.000Z"
}
GET /api/file/upload-sessions/:sessionId
Get upload session status.
Auth: Required
Response:
{
"sessionId": "session-uuid",
"filename": "video.mp4",
"uploadedChunks": [0, 1, 2],
"totalChunks": 20,
"status": "uploading"
}
PUT /api/file/upload-sessions/:sessionId/chunks/:chunkIndex
Upload file chunk.
Auth: Required
Content-Type: application/octet-stream
Body: Raw binary data
Response:
{
"chunkIndex": 0,
"received": true
}
POST /api/file/upload-sessions/:sessionId/finalize
Finalize chunked upload.
Auth: Required
Response:
{
"success": true,
"asset": {
"id": "asset-uuid",
"url": "https://cdn.example.com/video.mp4",
"storageKey": "uploads/video.mp4"
}
}
GET /api/file/download
Download file.
Query Parameters:
privateUrl- Encoded file pathid- Asset ID (alternative)
Response: File stream with appropriate Content-Type
POST /api/file/presign
Generate presigned URLs for batch asset downloads. For S3 storage, returns direct S3 signed URLs for client-side downloads (bypassing the backend). For other storage providers, returns backend proxy URLs.
Auth: Not required (public endpoint for runtime asset preloading)
Request:
{
"urls": [
"uploads/projects/abc/image1.jpg",
"uploads/projects/abc/video.mp4",
"uploads/projects/abc/audio.mp3"
]
}
Limits:
- Maximum 50 URLs per request
- All URLs must be non-empty strings
Response:
{
"presignedUrls": {
"uploads/projects/abc/image1.jpg": "https://bucket.s3.region.amazonaws.com/uploads/projects/abc/image1.jpg?X-Amz-...",
"uploads/projects/abc/video.mp4": "https://bucket.s3.region.amazonaws.com/uploads/projects/abc/video.mp4?X-Amz-...",
"uploads/projects/abc/audio.mp3": "https://bucket.s3.region.amazonaws.com/uploads/projects/abc/audio.mp3?X-Amz-..."
}
}
Presigned URL Expiry: 1 hour (3600 seconds)
Use Case: Frontend preloading uses this endpoint to get direct S3 download URLs, enabling:
- Parallel asset downloads without backend proxy overhead
- Direct storage in browser Cache API
- Blob URL creation for instant display
POST /api/file/upload/:table/:field
Legacy single-file upload.
Auth: Required
Content-Type: multipart/form-data
Projects Endpoints
POST /api/projects
Create a new project.
Auth: Required
Request:
{
"data": {
"name": "My Tour",
"slug": "my-tour",
"description": "A virtual tour",
"logo_url": "https://...",
"favicon_url": "https://...",
"og_image_url": "https://...",
"theme_config_json": {},
"custom_css_json": {},
"cdn_base_url": "https://cdn.example.com"
}
}
GET /api/projects
List all projects.
Auth: Optional (runtime public mode)
Query Parameters:
- Standard pagination/filtering
Response:
{
"rows": [
{
"id": "project-uuid",
"name": "My Tour",
"slug": "my-tour",
"tour_pages": [...],
"assets": [...]
}
],
"count": 10
}
GET /api/projects/:id
Get project by ID.
Auth: Optional (runtime public mode)
Includes: tour_pages, assets, project_audio_tracks, project_element_defaults
PUT /api/projects/:id
Update project.
Auth: Required
Request:
{
"id": "project-uuid",
"data": {
"name": "Updated Tour Name"
}
}
DELETE /api/projects/:id
Delete project.
Auth: Required
POST /api/projects/:id/clone
Clone project with all related entities.
Auth: Required
Response:
{
"id": "new-project-uuid",
"name": "My Tour (Copy)",
"slug": "my-tour-copy"
}
POST /api/publish/save-to-stage
Copy all dev environment content to stage for preview.
Auth: Required
Request:
{
"projectId": "project-uuid"
}
Response:
{
"success": true,
"publishEventId": "event-uuid",
"summary": {
"pages_copied": 10,
"audios_copied": 2
}
}
Note: This is part of the dev → stage → production workflow. Content is edited in dev (Constructor), previewed in stage, then published to production. Page elements, navigation, and transitions are stored in tour_pages.ui_schema_json and copied with pages.
Tour Pages Endpoints
POST /api/tour_pages
Create a tour page.
Auth: Required
Request:
{
"data": {
"title": "Home Page",
"slug": "home",
"sort_order": 0,
"projectId": "project-uuid",
"environment": "dev",
"background_image_url": "https://...",
"background_video_url": "https://...",
"ui_schema_json": {}
}
}
GET /api/tour_pages
List tour pages.
Auth: Optional (runtime public mode)
Query Parameters:
projectId- Filter by projectenvironment- Filter by environment
GET /api/tour_pages/:id
Get tour page by ID.
Includes: project
Note: Page elements are stored directly in the ui_schema_json field.
PUT /api/tour_pages/:id
Update tour page.
Auth: Required
POST /api/tour_pages/reorder
Update page order within a project/environment without touching page content.
Auth: Required
Request:
{
"data": {
"projectId": "project-uuid",
"environment": "dev",
"orderedPageIds": ["page-uuid-1", "page-uuid-2", "page-uuid-3"]
}
}
Behavior:
- Reordering is allowed only in
dev. orderedPageIdsmust contain every dev page in that project exactly once.- Duplicate IDs, missing IDs, IDs from another project, and unknown IDs are rejected.
- The backend updates only
sort_order; page content, slugs, navigation links, and media fields are not changed. - Stage receives the new order after
POST /api/publish/save-to-stage. - Production receives the new order after
POST /api/publish.
Response:
[
{ "id": "page-uuid-1", "sort_order": 1 },
{ "id": "page-uuid-2", "sort_order": 2 },
{ "id": "page-uuid-3", "sort_order": 3 }
]
Errors:
| Status | Reason |
|---|---|
| 400 | Missing projectId, invalid orderedPageIds, duplicate/missing pages, or environment other than dev |
| 403 | Authenticated user is not allowed to update pages in the project |
POST /api/tour_pages/:id/duplicate
Duplicate a dev tour page into a new independent dev page.
Auth: Required
Request:
{
"data": {
"projectId": "project-uuid",
"environment": "dev",
"name": "Lobby Copy",
"slug": "lobby-copy"
}
}
Behavior:
- Only dev pages can be duplicated. Stage and production are updated through Save to Stage and Publish.
- The duplicate receives a new page ID, unique slug, blank
source_key, andsort_order = max(project dev sort_order) + 1. - Page media/settings fields and
ui_schema_jsonare copied from the source page. - Inline element IDs and nested item IDs in
ui_schema_jsonare regenerated so the new page can be edited independently. - Asset URLs, transition URLs, and navigation
targetPageSlugvalues are preserved. - Existing reverse-video processing still runs through
TourPagesService, so transition reverse URLs are handled consistently with normal page save/create.
Response: Created tour page record.
Errors:
| Status | Reason |
|---|---|
| 400 | Missing source page, source page outside project, or non-dev source/target environment |
| 403 | Authenticated user is not allowed to create/update pages in the project |
DELETE /api/tour_pages/:id
Delete tour page.
Auth: Required
Constructor behavior: the constructor uses this same endpoint for the active dev page after showing a confirmation modal. After deletion it reloads page data and selects the next page in presentation order when available.
Assets Endpoints
POST /api/assets
Create an asset record.
Auth: Required
Request:
{
"data": {
"name": "Hero Image",
"cdn_url": "https://cdn.example.com/image.jpg",
"storage_key": "uploads/image.jpg",
"mime_type": "image/jpeg",
"checksum": "abc123...",
"width_px": 1920,
"height_px": 1080,
"size_mb": 0.5,
"duration_sec": null,
"projectId": "project-uuid"
}
}
GET /api/assets
List assets.
Auth: Required
Query Parameters:
projectId- Filter by projectmime_type- Filter by MIME type
Includes: asset_variants, project
GET /api/assets/:id
Get asset by ID.
Includes: asset_variants
PUT /api/assets/:id
Update asset.
Auth: Required
DELETE /api/assets/:id
Delete asset (and file from storage).
Auth: Required
Asset Variants Endpoints
POST /api/asset_variants
Create an asset variant.
Auth: Required
Request:
{
"data": {
"assetId": "asset-uuid",
"variant_type": "webp",
"cdn_url": "https://cdn.example.com/image.webp",
"storage_key": "uploads/image.webp",
"mime_type": "image/webp",
"width_px": 1920,
"height_px": 1080,
"size_bytes": 51200
}
}
Variant Types:
thumbnail- Small previewpreview- Medium previewwebp- WebP formatmp4_low- Low quality videomp4_high- High quality videooriginal- Original file
GET /api/asset_variants
List asset variants.
Auth: Required
Query Parameters:
assetId- Filter by parent assetvariant_type- Filter by variant type
Project Audio Tracks Endpoints
POST /api/project_audio_tracks
Create a project audio track.
Auth: Required
Request:
{
"data": {
"name": "Background Music",
"projectId": "project-uuid",
"audio_url": "https://cdn.example.com/music.mp3",
"duration_sec": 180,
"volume": 0.8,
"loop": true,
"autoplay": true
}
}
GET /api/project_audio_tracks
List audio tracks.
Auth: Optional (runtime public mode)
Query Parameters:
projectId- Filter by project
Project Memberships Endpoints
Manage team collaboration and per-project access control.
POST /api/project_memberships
Create a project membership (invite user to project).
Auth: Required
Request:
{
"data": {
"projectId": "project-uuid",
"userId": "user-uuid",
"access_level": "editor",
"is_active": true,
"invited_at": "2024-01-01T00:00:00.000Z"
}
}
Access Levels: owner, editor, reviewer, viewer
GET /api/project_memberships
List project memberships.
Auth: Required
Query Parameters:
projectIdorproject- Filter by projectuserIdoruser- Filter by useraccess_level- Filter by access levelis_active- Filter by active status
GET /api/project_memberships/:id
Get project membership by ID.
Auth: Required
Includes: project, user
PUT /api/project_memberships/:id
Update project membership.
Auth: Required
Request:
{
"id": "membership-uuid",
"data": {
"access_level": "viewer",
"is_active": false
}
}
DELETE /api/project_memberships/:id
Remove user from project.
Auth: Required
PWA Caches Endpoints
Track PWA cache versions and offline asset manifests per project.
POST /api/pwa_caches
Create a PWA cache record.
Auth: Required
Request:
{
"data": {
"projectId": "project-uuid",
"environment": "production",
"cache_version": "v1704067200000",
"manifest_json": {},
"asset_list_json": [],
"generated_at": "2024-01-01T00:00:00.000Z",
"is_active": true
}
}
Environment Values: dev, stage, production
GET /api/pwa_caches
List PWA cache records.
Auth: Required
Query Parameters:
projectIdorproject- Filter by projectenvironment- Filter by environmentis_active- Filter by active status
GET /api/pwa_caches/:id
Get PWA cache by ID.
Auth: Required
Includes: project
PUT /api/pwa_caches/:id
Update PWA cache record.
Auth: Required
DELETE /api/pwa_caches/:id
Delete PWA cache record.
Auth: Required
Users Endpoints
POST /api/users
Create a user.
Auth: Required (Admin)
Request:
{
"data": {
"email": "newuser@example.com",
"password": "password123",
"firstName": "John",
"lastName": "Doe",
"phoneNumber": "+1234567890",
"app_roleId": "role-uuid"
}
}
GET /api/users
List users.
Auth: Required
Searchable Fields: firstName, lastName, email, phoneNumber
GET /api/users/:id
Get user by ID.
Auth: Required
Includes: app_role
PUT /api/users/:id
Update user.
Auth: Required
DELETE /api/users/:id
Delete user.
Auth: Required (Admin)
Roles Endpoints
POST /api/roles
Create a role.
Auth: Required (Admin)
Request:
{
"data": {
"name": "Editor",
"globalAccess": false
}
}
GET /api/roles
List roles.
Auth: Required
GET /api/roles/:id
Get role by ID.
Includes: permissions
Permissions Endpoints
POST /api/permissions
Create a permission.
Auth: Required (Admin)
Request:
{
"data": {
"roleId": "role-uuid",
"entity": "projects",
"action": "read"
}
}
Actions: create, read, update, delete
Publishing Endpoints
The platform uses a three-tier publishing workflow:
┌─────────────────────────────────────────────────────────────────┐
│ Constructor (dev) Stage (preview) Production (live) │
│ dev ───► stage ───► production │
│ "Save to Stage" "Publish" │
└─────────────────────────────────────────────────────────────────┘
POST /api/publish/save-to-stage
Copy dev content to stage for preview. See Projects Endpoints.
POST /api/publish (or POST /api/publish/publish)
Publish project from stage to production environment. Both endpoints are aliases and perform the same action.
Auth: Required
Request:
{
"projectId": "project-uuid",
"title": "v1.0 Release",
"description": "Initial production release"
}
Response:
{
"success": true,
"publishEventId": "event-uuid",
"summary": {
"pages_copied": 10,
"audios_copied": 2
}
}
Note: Publishes stage environment content to production. Use save-to-stage first to copy changes from dev. Page elements, navigation links, and transitions are stored within tour_pages.ui_schema_json and copied automatically with pages.
Publish Events Endpoints
GET /api/publish_events
List publish events.
Auth: Required
Query Parameters:
projectId- Filter by project
Response:
{
"rows": [
{
"id": "event-uuid",
"projectId": "project-uuid",
"title": "v1.0 Release",
"description": "Initial release",
"publishedAt": "2024-01-01T00:00:00.000Z",
"createdBy": "user-uuid"
}
],
"count": 5
}
Access Logs Endpoints
POST /api/access_logs
Create an access log entry.
Auth: Required
Request:
{
"data": {
"project": "project-uuid",
"user": "user-uuid",
"environment": "production",
"path": "/api/tour_pages",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"accessed_at": "2024-01-01T00:00:00.000Z"
}
}
Environment Values: admin, stage, production
GET /api/access_logs
List access logs.
Auth: Required
Searchable Fields: path, ip_address, user_agent
Query Parameters:
project- Filter by project ID or nameuser- Filter by user ID or nameenvironment- Filter by environment (admin/stage/production)accessed_atRange- Filter by date range
Presigned URL Requests Endpoints
Track and audit presigned URL generation requests.
POST /api/presigned_url_requests
Create a presigned URL request record.
Auth: Required
Request:
{
"data": {
"requested_key": "uploads/projects/abc/image.jpg",
"mime_type": "image/jpeg",
"status": "pending",
"requested_size_mb": 2.5,
"expires_at": "2024-01-01T01:00:00.000Z"
}
}
Status Values: pending, completed, expired, failed
GET /api/presigned_url_requests
List presigned URL requests.
Auth: Required
Query Parameters:
status- Filter by statusrequested_key- Filter by storage key
GET /api/presigned_url_requests/:id
Get presigned URL request by ID.
Auth: Required
PUT /api/presigned_url_requests/:id
Update presigned URL request.
Auth: Required
DELETE /api/presigned_url_requests/:id
Delete presigned URL request.
Auth: Required
Global UI Control Defaults Endpoints
Global UI controls are the system-owned fullscreen, sound, and offline buttons. Runtime settings resolve through:
global_ui_control_defaults → project_ui_control_settings → tour_pages.global_ui_controls_settings_json
GET /api/global-ui-control-defaults
Get singleton platform defaults.
Auth: Not required for runtime reads
PUT /api/global-ui-control-defaults/:id
Update singleton platform defaults.
Auth: Required
GET /api/project-ui-control-settings/project/:projectId/env/:environment
Get project/environment overrides. environment is dev, stage, or
production.
Auth: Required for dev and stage. Production is public for public
presentations and requires JWT/access grants for private production
presentations.
PUT /api/project-ui-control-settings/project/:projectId/env/:environment
Upsert project/environment overrides.
Auth: Required
DELETE /api/project-ui-control-settings/project/:projectId/env/:environment
Delete project/environment overrides so runtime falls back to global defaults.
Auth: Required
Element Type Defaults Endpoints
Global platform-wide default settings for each element type. These are the source of truth that get snapshotted to project_element_defaults when a project is created.
Alias: /api/ui-elements routes to the same endpoints as /api/element-type-defaults.
Note: The Constructor page uses project_element_defaults (not this endpoint) to fetch element defaults for the current project. This endpoint is for platform-wide administration of default settings.
GET /api/element-type-defaults
List all element type defaults.
Auth: Required
Response:
{
"rows": [
{
"id": "uuid",
"element_type": "navigation_next",
"name": "Navigation: Forward",
"sort_order": 1,
"is_active": true,
"default_settings_json": {
"width": "60px",
"height": "60px",
"opacity": 1
}
}
],
"count": 11
}
GET /api/element-type-defaults/:id
Get element type default by ID.
Auth: Required
PUT /api/element-type-defaults/:id
Update element type default settings.
Auth: Required (Admin)
Request:
{
"id": "uuid",
"data": {
"default_settings_json": {
"width": "80px",
"height": "80px"
}
}
}
Project Element Defaults Endpoints
Project-specific default settings for UI elements. These are automatically snapshotted from global defaults (element_type_defaults) when a project is created. The Constructor page uses this endpoint to fetch element defaults for the current project.
Three-Tier Element Defaults Hierarchy:
element_type_defaults (global) → project_element_defaults (project) → tour_pages.ui_schema_json (instance)
GET /api/project-element-defaults
List project element defaults.
Auth: Required
Query Parameters:
projectIdorproject- Filter by project ID or name (recommended)- Supports
|pipe separator for multiple values
Response:
{
"rows": [
{
"id": "uuid",
"projectId": "project-uuid",
"element_type": "navigation_next",
"name": "Navigation: Forward",
"sort_order": 1,
"settings_json": {
"width": "60px",
"height": "60px"
},
"source_element_id": "global-default-uuid",
"snapshot_version": 1
}
],
"count": 11
}
GET /api/project-element-defaults/:id
Get project element default by ID.
Auth: Required
PUT /api/project-element-defaults/:id
Update project-specific default settings.
Auth: Required
Request:
{
"id": "uuid",
"data": {
"settings_json": {
"width": "100px",
"backgroundColor": "#ff0000"
}
}
}
POST /api/project-element-defaults/:id/reset
Reset project default to current global default. Copies settings from element_type_defaults and increments snapshot_version.
Auth: Required
Response: Returns the updated project element default record:
{
"id": "uuid",
"projectId": "project-uuid",
"element_type": "navigation_next",
"name": "Navigation: Forward",
"sort_order": 1,
"settings_json": { "width": "60px", "height": "60px" },
"source_element_id": "global-default-uuid",
"snapshot_version": 2,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-15T00:00:00.000Z"
}
Error: Returns 500 if global default not found for the element type.
GET /api/project-element-defaults/:id/diff
Compare project default with current global default.
Auth: Required
Response:
{
"projectDefault": {
"id": "uuid",
"element_type": "navigation_next",
"settings_json": { "width": "100px" }
},
"globalDefault": {
"id": "global-uuid",
"element_type": "navigation_next",
"default_settings_json": { "width": "60px" }
},
"hasGlobalDefault": true,
"isDifferent": true,
"projectSettings": { "width": "100px" },
"globalSettings": { "width": "60px" }
}
Response when global default not found:
{
"projectDefault": { ... },
"globalDefault": null,
"hasGlobalDefault": false,
"isDifferent": true
}
Search Endpoint
POST /api/search
Search across all entities. Searches both text fields and numeric fields (cast to text for matching).
Auth: Required
Rate Limit: 30 requests per minute per IP
Request:
{
"searchQuery": "keyword"
}
Response:
Returns a flat array of matching records from all searchable tables. Each record includes tableName and matchAttribute fields to identify the source and matching fields.
[
{
"id": "uuid-1",
"name": "My Project",
"slug": "my-project",
"tableName": "projects",
"matchAttribute": ["name", "slug"]
},
{
"id": "uuid-2",
"title": "Home Page",
"tableName": "tour_pages",
"matchAttribute": ["title"]
}
]
Searchable Tables & Fields:
| Table | Text Fields | Numeric Fields |
|---|---|---|
users |
firstName, lastName, phoneNumber, email | - |
projects |
name, slug, description, logo_url, favicon_url, og_image_url | - |
assets |
name, cdn_url, storage_key, mime_type, checksum | size_mb, width_px, height_px, duration_sec |
asset_variants |
cdn_url | width_px, height_px, size_mb |
presigned_url_requests |
requested_key, mime_type, status | requested_size_mb |
tour_pages |
source_key, name, slug, background_image_url, background_video_url, background_audio_url, ui_schema_json | sort_order |
project_audio_tracks |
source_key, name, slug, url | volume, sort_order |
publish_events |
error_message | pages_copied, transitions_copied, audios_copied |
pwa_caches |
cache_version, manifest_json, asset_list_json | - |
access_logs |
path, ip_address, user_agent | - |
Permission Check: Search results are filtered based on user permissions. Only tables where user has READ_{TABLE_NAME} permission are searched.
Limit: Maximum 50 results per table.
Bulk Operations
POST /api/{entity}/deleteByIds
Bulk delete entities.
Auth: Required
Request:
{
"data": ["uuid-1", "uuid-2", "uuid-3"]
}
Response:
{
"deleted": 3
}
POST /api/{entity}/bulk-import
Bulk import from CSV.
Auth: Required
Content-Type: multipart/form-data
Form Fields:
file- CSV fileimportHash- Unique import identifier
Response:
{
"imported": 50,
"errors": []
}
CSV Export
Add ?filetype=csv to any list endpoint to export as CSV.
Example:
GET /api/projects?filetype=csv&limit=1000
Response: CSV file download with appropriate headers
Swagger Documentation
Interactive API documentation available at:
GET /api-docs
Provides Swagger UI with all endpoints, request/response schemas, and testing capabilities.