Set Up Bundle Archive Uploads
How archive uploads are validated, extracted, and tracked after adaptive transfer completion.
Bundle archive uploads are intended for large photo sets and other file collections that are easier to transfer as one archive than as many individual files. The transfer itself uses the adaptive bundle upload flow described in Set Up Bundle Uploads.
Flow
- Call
GET /v1/spatial/bundles/archive-upload-supportto read the supported formats and current server limits. - Call
POST /v1/spatial/locations/{locationId}/bundles/archive-upload-start. - Transfer the archive using the returned direct upload target or upload session.
- Complete the direct upload or session. Completion enqueues extraction in the background-jobs host and returns
archiveImportTaskId. - Poll
GET /v1/spatial/bundles/archive-imports/{taskId}until the task reaches a terminal state.
After extraction succeeds, the files live in the same bundle layout used by regular per-file bundle uploads. Clients can list bundle metadata, inspect bundle files, request a ZIP download, or start a configured pipeline job for the bundle.
Authorization and storage accounting
Archive upload issuance and completion require final
LocationBundles=Write. The declared compressed bytes are reserved before the
bundle and upload state are created. Completing the transfer enqueues
extraction but deliberately leaves that reservation active: the source archive
is staging data, and its compressed size is not the durable size of the
resulting bundle.
The background finalizer resolves the current requester again. PAT requests
must still have a valid token with the required organization and capability
ceilings. It then rechecks LocationBundles=Write and Bundle capacity and, in
one transaction, attaches the full extracted file set and commits the exact
expanded object bytes. Failure before that commit deletes staged objects and
releases the reservation. The source archive is deleted after success or
failure.
Normal imported artifact kinds are classified as Bundle storage. A legacy or mixed bundle can contain a Document-classified artifact; exposing that file or a full bundle ZIP also requires its final path-aware Document read permission. Generated bundle ZIPs are rebuildable, non-billable derived caches and are only exposed after a current authorization check.
Archive sessions use the shared session transfer rules: only the user who created the session can inspect, transfer, complete, or cancel it, current bundle write access is re-checked on every request, and URL refresh stops once the session expires or leaves pending/uploading transfer state.
File completion is idempotent after the archive file reaches uploaded or completed. If a file-complete response is lost, repeat that request to receive the persisted file state without completing the object-storage upload again. Multipart retries also reconcile an exact-size stored object when object storage completed the upload before the API could persist the result. If the session-complete response is lost, repeat session completion. Only one request owns finalization; concurrent or replayed requests return HTTP 200 with session.status and result.status set to finalizing, result.succeeded set to false, and no error while the owner finishes. Poll GET /v1/upload-sessions/{sessionId} until terminal. Entering finalizing extends expiresAtUtc with a bounded server-managed lease, so cleanup skips live work and can reclaim a crashed finalizer after the lease expires. An already completed archive session returns its persisted bundleId without enqueueing extraction again. The winning archive-completion response is currently the only response that carries archiveImportTaskId, so clients must retain that value. A finalizing session cannot be canceled.
Supported formats
The support endpoint is the source of truth, but the current server support includes:
.zip.7z.tar.tar.gz.tgz
Encrypted archives are rejected. The importer also rejects symlinks, absolute paths, path traversal attempts, duplicate normalized targets, and archives that exceed configured limits.
By default the importer strips one shared top-level folder. For example, if every entry is under drone-run-001/, imported bundle files start below that folder instead of keeping it as an extra root directory.
Status behavior
The archive import status response includes:
taskIdbundleIdarchiveFileNamestatusprogressPercentprogressBytestotalBytesstatusMessageerror
status is one of Queued, Running, Succeeded, Failed,
AuthorizationChanged, or CapacityChanged. The last two are stable terminal
results from the final policy recheck; error is respectively
authorization_changed or capacity_changed.
If extraction, final authorization, or the final capacity commit fails, no new file record becomes visible. Staged objects are quarantined from visibility for bounded cleanup, and the active reservation is released so the bundle does not remain partially populated. Retry by starting a fresh archive upload; the next task publishes its complete file set once or publishes nothing.
Removal
Use DELETE /v1/spatial/bundles/{bundleId} to remove an imported bundle.
This endpoint currently performs an immediate hard delete:
- The bundle row is removed from the database.
- Stored bundle file records are removed from the database.
- The extracted bundle objects are removed from object storage.
- Uploaded source archive objects under the bundle prefix are removed from object storage.
- Generated bundle ZIP archives are removed from object storage.
The database mutation is atomic. If another live resource still prevents deletion, the API returns
409 Conflict and leaves both database rows and object-storage data unchanged. Queued, reserved,
and running Jobs block deletion; cancel or complete them first. Terminal Job history remains
available with references to the deleted bundle or bundle input files cleared.
Object-storage deletion runs after the database commit from a durable BackgroundJobs cleanup record. Cleanup is idempotent and retried after storage failures, so a successful API response can briefly precede physical object removal.
There is no retention window or restore flow yet. Clients should present this as irreversible confirmation before calling the delete endpoint.