Appearance
Projects API
Manage projects through the REST API. All endpoints require authentication.
List Projects
http
GET /api/projects/
Authorization: Bearer <token>Response:
json
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "550e8400-...",
"name": "My Mall",
"description": "Shopping center map",
"organization": "org-uuid",
"organization_name": "My Company",
"group": null,
"group_name": null,
"status": "PUBLISH",
"settings": {
"defaultLevelId": "level-uuid",
"scrollMode": "default",
"theme": "auto",
"defaultLanguage": "en"
},
"appearance": {
"isZoomControlsVisible": true,
"isSearchBarVisible": true,
"isLevelSwitcherVisible": true,
"canvasBackgroundColor": "#ffffff",
"canvasBorderRadius": "large",
"routeColor": "#0066cc",
"routeWidth": 5,
"hidePoweredBy": false,
"customCss": ""
},
"analytics": {
"isEnabled": true,
"enabledEvents": []
},
"thumbnail": null,
"created_at": "2026-04-01T10:00:00Z",
"updated_at": "2026-04-12T14:30:00Z",
"live_updated_at": "2026-04-10T12:00:00Z"
}
]
}Get Project
http
GET /api/projects/{id}/
Authorization: Bearer <token>Returns the full project with nested levels, areas, markers, tags, languages, wayfinding, and translations.
Create Project
http
POST /api/projects/
Authorization: Bearer <token>
Content-Type: application/json
{
"organization": "org-uuid",
"name": "My Mall",
"description": "Shopping center map",
"group": "group-uuid"
}The project is created in Draft status. Draft and publish limits are enforced based on your subscription plan.
Response: Full project object (same as Get).
Update Project
http
PATCH /api/projects/{id}/
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Updated Name",
"settings": {
"defaultLevelId": "level-uuid",
"scrollMode": "ctrl",
"theme": "dark",
"defaultLanguage": "ru"
},
"appearance": {
"isSearchBarVisible": false,
"canvasBorderRadius": "none"
}
}TIP
Use PATCH for partial updates — only include the fields you want to change.
Delete Project
http
DELETE /api/projects/{id}/
Authorization: Bearer <token>DANGER
Deleting a project permanently removes all levels, areas, markers, and analytics data.
Publish / Unpublish
Publish
http
POST /api/projects/{id}/publish/
Authorization: Bearer <token>Publishing makes the project accessible via the embed URL and public API. Checks:
- Subscription must be active (paid plans)
- Must not exceed organization or group build limit
Unpublish
http
POST /api/projects/{id}/unpublish/
Authorization: Bearer <token>Moves the project back to Draft. The embed URL stops working.
Update Live
http
POST /api/projects/{id}/update-live/
Authorization: Bearer <token>Pushes latest changes to the published version without changing status. Only works for already published projects.
Archive / Restore
Archive
http
POST /api/projects/{id}/archive/
Authorization: Bearer <token>Restore
http
POST /api/projects/{id}/restore/
Authorization: Bearer <token>Restores an archived project back to Draft status.
Duplicate
http
POST /api/projects/{id}/duplicate/
Authorization: Bearer <token>
Content-Type: application/json
{ "name": "Custom name" }Creates a deep copy of the project as a new Draft. Body fields are optional — when name is omitted the copy is auto-named "{original} (Copy)", falling back to (Copy 2), (Copy 3), ... if that name is already in use.
Copied: all levels (with their image files), areas, markers, tags, translations, project languages, settings, appearance, analytics configuration, and wayfinding (corridors, branches, transitions).
Not copied: version history snapshots, accumulated analytics events, and the published live snapshot. The copy is always created as Draft, even if the source is Published.
Errors:
403 plan_limit_reached— org or group draft limit would be exceeded403— viewer role400—namecollides with an existing project in the same organization
Snapshots (Version History)
Pro & EnterpriseVersion history requires a Pro or Enterprise subscription.
Compare plansList Snapshots
http
GET /api/projects/{id}/snapshots/
Authorization: Bearer <token>Response:
json
[
{
"id": "snapshot-uuid",
"created_at": "2026-04-12T14:30:00Z"
}
]Restore Snapshot
http
POST /api/projects/{id}/snapshots/{snapshot_id}/restore/
Authorization: Bearer <token>Tags
List Tags
http
GET /api/projects/{id}/tags/
Authorization: Bearer <token>Response:
json
[
{ "id": "tag-uuid", "name": "Food", "color": "#FF5733", "translations": { "de": "Essen" } },
{ "id": "tag-uuid", "name": "Shopping", "color": "#3366FF", "translations": {} }
]name is the default-language name; translations maps every other language code to its name. A language that is missing from translations falls back to name on the map.
Create Tag
http
POST /api/projects/{id}/tags/
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Services",
"color": "#9E9E9E",
"translations": { "de": "Dienstleistungen" }
}translations is optional. Empty names are dropped, and an entry for the default language is ignored — that text is name.
Update Tag
http
PATCH /api/projects/{id}/tags/{tag_id}/
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Updated Name",
"color": "#00AA00"
}Delete Tag
http
DELETE /api/projects/{id}/tags/{tag_id}/
Authorization: Bearer <token>Images
Upload Image
http
POST /api/projects/{id}/upload-image/
Authorization: Bearer <token>
Content-Type: multipart/form-data
file=<image>Response:
json
{
"url": "https://...",
"path": "projects/uuid/image.png",
"size": 204800
}Accepted types are JPEG, PNG, GIF, WebP and SVG, detected from the file content rather than the filename. The returned path carries the detected extension. SVGs are sanitized before storage. Files over 5 MB, unrecognised formats and non-image content named like an image return 400 {"error": "..."}. The same checks apply to images sent inside a project PATCH, see Entities → Upload Image.
Browse Images
http
GET /api/projects/{id}/images/?page=1&page_size=12
Authorization: Bearer <token>Response:
json
{
"images": ["https://..."],
"page": 1,
"pageSize": 12,
"totalImages": 48,
"totalPages": 4
}Project Statuses
| Status | Description |
|---|---|
DRAFT | Work in progress. Not publicly accessible. |
PUBLISH | Live. Accessible via embed and public API. |
ARCHIVE | Archived. Not accessible, can be restored. |
EXPIRED | Reserved status — not produced by the normal publish/billing flows (a lapsed subscription moves projects to DRAFT). Treat as not publicly accessible. |