Set Up Document Uploads

How to implement the upload-start, storage upload, and upload-complete flow for document libraries.

Document uploads use a two-step API flow around direct object-storage transfer:

  1. Call the matching upload-start endpoint.
  2. Upload the file to the returned storage URL.
  3. Call the matching upload-complete endpoint to persist the document row.

Use the cluster, location, or organization upload endpoints depending on where the document should appear:

POST /v1/spatial/clusters/{clusterId}/documents/upload-start
POST /v1/spatial/clusters/{clusterId}/documents/upload-complete
POST /v1/spatial/locations/{locationId}/documents/upload-start
POST /v1/spatial/locations/{locationId}/documents/upload-complete
POST /v1/orgs/{organizationId}/documents/upload-start
POST /v1/orgs/{organizationId}/documents/upload-complete

Read document metadata from:

GET /v1/spatial/documents/{documentId}
GET /v1/spatial/documents
GET /v1/spatial/clusters/{clusterId}/documents
GET /v1/spatial/locations/{locationId}/documents
GET /v1/orgs/{organizationId}/documents

Use GET /v1/spatial/documents without clusterIds for documents attached directly to all clusters the current user can read, or provide clusterIds as repeated query values or a comma-separated list for a selected-cluster document library.

Document list endpoints accept folderPath and recursive. Omit folderPath for all documents in the scope, send folderPath= for root-level documents, or send a path like folderPath=permits/2026 for one folder. Add recursive=true to include descendant folders.

Location documents can be linked to spatial annotations with documentIds on the annotation create and update payloads. The annotation stores document ids, so folder moves and filename changes do not break the link. When a linked document is deleted, it is no longer returned in the annotation documents list.

Folders

Folders are logical document metadata. Moving a document or renaming a folder updates the document folderPath; it does not move or rename the underlying object-storage key.

Always pass the bucket and objectKey returned by upload-start back to upload-complete. New location-scoped uploads use a physical locations/{locationId}/documents/... object prefix, while folderPath remains the logical folder shown in document library responses.

Manage folder trees with:

GET /v1/spatial/clusters/{clusterId}/documents/folders
POST /v1/spatial/clusters/{clusterId}/documents/folders
PATCH /v1/spatial/clusters/{clusterId}/documents/folders/{folderId}
DELETE /v1/spatial/clusters/{clusterId}/documents/folders/{folderId}
GET /v1/spatial/locations/{locationId}/documents/folders
POST /v1/spatial/locations/{locationId}/documents/folders
PATCH /v1/spatial/locations/{locationId}/documents/folders/{folderId}
DELETE /v1/spatial/locations/{locationId}/documents/folders/{folderId}
GET /v1/orgs/{organizationId}/documents/folders
POST /v1/orgs/{organizationId}/documents/folders
PATCH /v1/orgs/{organizationId}/documents/folders/{folderId}
DELETE /v1/orgs/{organizationId}/documents/folders/{folderId}
PATCH /v1/spatial/documents/{documentId}/folder

Use parentPath on folder list endpoints to list one level below a parent folder. Creating or uploading into permits/2026 creates missing ancestor folders such as permits. Deleting a folder requires it to have no child folders and no documents.

{
  "path": "permits/2026"
}

Metadata

upload-complete accepts documentType, customMetadata, and clearCustomMetadata.

customMetadata must be a JSON object and is limited to 16384 bytes after serialization. Omit it to preserve existing metadata when replacing a document, or send clearCustomMetadata: true to remove existing metadata.

{
  "bucket": "pixservice-dev",
  "objectKey": "user/11111111-1111-1111-1111-111111111111/locations/22222222-2222-2222-2222-222222222222/documents/permits/2026/site-a.pdf",
  "contentType": "application/pdf",
  "sizeBytes": 482193,
  "checksumSha256": "f32e6d1775c8baf5b7d560a9304f7b34cfe1bbab2d9f8d3f8fd3db2cc7d6b2d0",
  "originalFileName": "site-a.pdf",
  "documentType": "Permit",
  "folderPath": "permits/2026",
  "customMetadata": {
    "trade": "electrical",
    "revision": 3
  }
}

If upload-complete finds that the object key already belongs to a different document scope, it returns 409 Conflict problem details without exposing the owning document, location, bucket, or object key. Ask the user to rename the file and retry the upload.

Comments

Document comments are stored by PixService and use the same file permissions as the document.

GET /v1/spatial/documents/{documentId}/comments
POST /v1/spatial/documents/{documentId}/comments
PATCH /v1/spatial/documents/{documentId}/comments/{commentId}
DELETE /v1/spatial/documents/{documentId}/comments/{commentId}

Users with read access can list comments. Users with current write access can create comments, and can edit or delete only comments they authored. Comment responses include the author's username, display name, and temporary profile-picture link when one exists.

On this page