Floorplan Collections API guide
This guide covers the four API endpoints that support the floorplan collections feature — a way to organize plans into named folder groups within a project or project template.
Prerequisite: Collections must be enabled on a project before you can use the relevant project endpoints below.
Endpoints
| Method | Path | Purpose |
|---|---|---|
PATCH/PUT | /api/v3/projects/{project_id}/floorplans/flags/collections | Enable the collections feature flag on a project |
POST | /api/v3/projects/{project_id}/floorplans/batch_move | Move floorplans into a collection folder |
POST | /api/v3/projects/{project_id}/folders/{id}/duplicate | Duplicate a project-level collection folder |
POST | /api/v3/account/project_template_folders/{id}/duplicate | Duplicate a project template collection folder |
1. Enable Collections on a Project
PATCH /api/v3/projects/{project_id}/floorplans/flags/collections
Enables the floorplan collections feature flag for the given project. This also creates a default collection folder with the name you provide. This flag can only be enabled — it cannot be set back to false.
This endpoint must be called beforebatch_movewill work.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
project_id | UUID | ID of the project |
Request Body
{
"value": true,
"default_collection_name": "Default Collection"
}| Field | Type | Required | Description |
|---|---|---|---|
value | boolean | ✅ | Must be true |
default_collection_name | string | ✅ | Name of the initial default collection folder to create |
last_editor_user_id | integer | API key only | ID of the user performing the action |
Responses
| Status | Description |
|---|---|
201 | Flag enabled — returns the new project_flag object |
422 | Flag is already enabled, or required fields are missing |
Example
curl -X PATCH "https://client-api.us.fieldwire.com/api/v3/projects/{project_id}/floorplans/flags/collections" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"value": true,
"default_collection_name": "Default Collection"
}'201 response:
{
"id": "f1a2b3c4-...",
"project_id": "...",
"name": "is_collections_enabled",
"value": true,
"creator_user_id": 123,
"last_editor_user_id": 123,
"created_at": "2026-03-03T10:00:00.000000Z",
"updated_at": "2026-03-03T10:00:00.000000Z"
}Authorization
Requires project admin role.
2. Batch Move Floorplans into a Collection
POST /api/v3/projects/{project_id}/floorplans/batch_move
Moves one or more floorplans into a target folder collection (or back to the root/unfiled level). The operation is asynchronous and processed via a background worker — the endpoint returns 200 OK immediately once the job is enqueued.
Requires collections to be enabled. Call the Enable Collections endpoint first.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
project_id | UUID | ID of the project |
Request Body
{
"floorplan_ids": ["uuid-1", "uuid-2"],
"folder_id": "target-folder-uuid"
}| Field | Type | Required | Description |
|---|---|---|---|
floorplan_ids | UUID[] | ✅ | List of floorplan IDs to move. Must not be empty. Maximum size is determined by FLOORPLAN_MOVE_BATCH_SIZE × FLOORPLAN_MOVE_BATCHES_LIMIT. |
folder_id | UUID | null | ✅ | ID of the destination collection folder. Pass null to move floorplans to the root (unfiled) level. |
last_editor_user_id | integer | API key only | ID of the user performing the action |
Responses
| Status | Description |
|---|---|
200 | Move job enqueued successfully |
422 | Collections are not enabled, validation failed (e.g. empty list, source equals target, too many floorplans) |
Example — Move to a Collection
curl -X POST "https://client-api.us.fieldwire.com/api/v3/projects/{project_id}/floorplans/batch_move" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"floorplan_ids": ["uuid-1", "uuid-2"],
"folder_id": "target-collection-uuid"
}'Example — Move Back to Root (Unfiled)
curl -X POST "https://client-api.us.fieldwire.com/api/v3/projects/{project_id}/floorplans/batch_move" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"floorplan_ids": ["uuid-1"],
"folder_id": null
}'Authorization
Requires the Plan Upload role on the project.
3. Duplicate a Project Folder Collection
POST /api/v3/projects/{project_id}/folders/{id}/duplicate
Duplicates a folder collection and all of its contents (floorplans, nested folders, etc.) within a project. This is an async operation — on the first call the server enqueues a background job and returns a jid. Poll the same endpoint with ?jid=<jid> until a 200 with the duplicated folder is returned.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
project_id | UUID | ID of the project |
id | UUID | ID of the folder collection to duplicate |
Request Body
{
"folder": {
"name": "Copy of Level 1 Plans"
}
}| Field | Type | Required | Description |
|---|---|---|---|
folder.name | string | ✅ | Name for the duplicated folder |
Responses
| Status | Description |
|---|---|
200 | Duplication complete — returns the new folder object |
202 | Job enqueued — response body contains { "jid": "<job_id>" }. Re-send the request with ?jid=<job_id> to poll for the result. |
Example — Initial Request
curl -X POST "https://client-api.us.fieldwire.com/api/v3/projects/{project_id}/folders/{id}/duplicate" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "folder": { "name": "Copy of Level 1 Plans" } }'202 response:
{ "jid": "abc123def456" }Example — Polling
curl -X POST "https://client-api.us.fieldwire.com/api/v3/projects/{project_id}/folders/{id}/duplicate?jid=abc123def456" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "folder": { "name": "Copy of Level 1 Plans" } }'200 response:
{
"id": "e4b1f3a2-...",
"name": "Copy of Level 1 Plans",
"kind": "floorplan",
"project_id": "...",
...
}Authorization
Requires the Plan Upload role on the project.
4. Duplicate a Project Template Folder Collection
POST /api/v3/account/project_template_folders/{id}/duplicate
Duplicates a project template folder collection and all of its contents. Same async polling pattern as the project-level duplicate above.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | UUID | ID of the project template folder collection to duplicate |
Request Body
{
"project_template_folder": {
"name": "Copy of Structural Plans"
}
}| Field | Type | Required | Description |
|---|---|---|---|
project_template_folder.name | string | ✅ | Name for the duplicated folder |
Responses
| Status | Description |
|---|---|
200 | Duplication complete — returns the new project_template_folder object |
202 | Job enqueued — poll with ?jid=<jid> |
Authorization
Requires create permission on ProjectTemplateFolder (account admin).
Typical Workflow
1. Enable collections on the project
PATCH /api/v3/projects/{project_id}/floorplans/flags/collections
{ "value": true, "default_collection_name": "Default Collection" }
2. Create additional collection folders (optional)
POST /api/v3/projects/{project_id}/folders
{ "folder": { "name": "Level 1 Plans", "kind": "floorplan" } }
3. Move floorplans into a collection
POST /api/v3/projects/{project_id}/floorplans/batch_move
{ "floorplan_ids": [...], "folder_id": "collection-uuid" }
4. Duplicate a collection when needed
POST /api/v3/projects/{project_id}/folders/{id}/duplicate
{ "folder": { "name": "Copy of Level 1 Plans" } }
→ poll with ?jid=<jid> until 200Updated 2 days ago