---
title: "Complete signed uploads in bulk"
method: POST
path: "/assets/complete"
tags: ["Assets"]
---

# Complete signed uploads in bulk

`POST /assets/complete`

## Request

- Base URL: `https://app.flora.ai/api/v1`
- URL: `https://app.flora.ai/api/v1/assets/complete`
- Auth: HTTP bearer

Completes up to 25 signed uploads in one request — the batch counterpart of POST /assets/{assetId}/complete, counted once against the workspace's rate limit instead of once per file. Every asset is verified and validated as the single completion does. Each entry echoes its index and asset_id and reports status ready, or failed with failure_message, exactly as the single completion would; ok is false with an error only when completion could not run for that asset — an id that is missing, deleted or outside this credential's write access reports not_found, the single completion's deliberate ambiguity. A failed entry never stops the rest, and a repeated id completes once and reports under each index. Static media reserved with project_id are surfaced on that project's canvas without stacking on one another; GLB Model3D assets are associated with the project but are not auto-placed. A malformed asset_id rejects the whole request. Mutating public API requests support an optional Idempotency-Key header for client retries; duplicate keys within two hours return idempotency_duplicate, and a batch whose every entry was rejected releases its key (see the Idempotency guide).

## Request body

- object
  - `asset_ids` string[], required: Signed-upload asset ids (asset_…) to complete, 1 to 25 per call

## Response `200`

Uploads completed; each entry reports its own outcome.

- object
  - `assets` union[], required: One entry per requested asset id, in request order: ok true with the single completion's fields, or ok false with error
    - union
      - object
        - `asset_id` string, required: Asset identifier
        - `url` string, uri, nullable, required: Asset URL
        - `workspace_id` string, nullable, required: Workspace identifier
        - `visibility` 'workspace', required
        - `status` 'pending_upload' | 'ready' | 'failed', required
        - `failure_message` string, nullable, required: Why the upload failed when status is failed; null otherwise
        - `index` integer, required: Position of this entry in the request's list
        - `ok` true, required: Completion ran; status reports ready or failed, as on the single completion
      - object
        - `index` integer, required: Position of this entry in the request's list
        - `asset_id` string, required: The id from the request, echoed
        - `ok` false, required: This entry failed; error says why
        - `error` object, required: Why this entry failed
          - `code` string, required: Stable public API error code, as the single-asset operation would return it
          - `message` string, required: Human-readable reason this entry failed

## Other responses

- `400`: 400
- `401`: 401
- `402`: 402
- `403`: 403
- `404`: 404
- `409`: 409
- `429`: 429
- `500`: 500
- `503`: 503

## Changes

- **2026-10-28** `a8351619f225`: 9 warning
  - added the new `not_configured` enum value to the `error/code` response property for the response status `400`
  - added the new `not_configured` enum value to the `error/code` response property for the response status `401`
  - added the new `not_configured` enum value to the `error/code` response property for the response status `402`
  - added the new `not_configured` enum value to the `error/code` response property for the response status `403`
  - …5 more
- **2026-10-16** `e54130373b10`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/florafauna-ai/apis/flora-ai-api/changes/assets/complete/post.md)

---

[API](https://skmtc.dev/florafauna-ai/apis/flora-ai-api.md) - [All operations](https://skmtc.dev/florafauna-ai/apis/flora-ai-api/llms.txt) - [OpenAPI document](https://skmtc.dev/florafauna-ai/apis/flora-ai-api/revisions/87cfe2c4ac29?raw)
