---
title: "Update metadata on multiple assets"
method: POST
path: "/api/assets/bulk-update"
tags: ["assets"]
---

# Update metadata on multiple assets

`POST /api/assets/bulk-update`

Updates metadata on multiple assets in one transactional call. Each item carries the target asset id and the per-asset change — different fields can be changed on different assets in the same request. Atomic: any per-item validation failure or unknown / cross-user id rejects the whole batch and writes nothing.

For a single-asset edit, prefer `update_asset` — semantically identical but slightly more concise at the call site.

## Request body

- BulkUpdateAssetsRequest — Bulk-update request body — heterogeneous per-asset changes in one call.
  - `updates` BulkUpdateAssetItem[], required — List of per-asset updates. Each item carries the target asset id and the change to apply to it; different fields can be changed on different assets in the same request. Up to 200 items per request.
    - `id` string, required — Asset ID (with the `asset_` prefix) to apply this change to.
    - `change` UpdateAssetRequest, required — User-editable metadata for a single asset.
      - `description` string, nullable — User-set description for the asset. Pass `null` to remove a previously-set value; the effective response may still contain a description from another metadata source. Omit to leave unchanged. Distinct from the AI-generated `description` field on the response — this writes to `metadata.description`.
      - `latitude` number, nullable — GPS latitude in decimal degrees, `[-90, 90]`. Must be set together with `longitude`. Pass `null` (along with `longitude=null`) to remove a previously-set value; omit to leave unchanged.
      - `longitude` number, nullable — GPS longitude in decimal degrees, `[-180, 180]`. Must be set together with `latitude`. Pass `null` (along with `latitude=null`) to remove a previously-set value; omit to leave unchanged.
      - `original_datetime` string, date-time, nullable — When the asset was originally captured. Timezone-aware values preserve their UTC offset; timezone-naive values have no offset. Pass `null` to remove a previously-set value; the effective response may still contain a datetime from another metadata source. Omit to leave unchanged.

## Response `200`

Successful Response

- BulkUpdateAssetsResponse — Empty acknowledgment returned by `bulk_update_assets`.

## Other responses

- `401` — Missing, invalid, or expired credentials.
- `403` — The credentials are valid but not authorized for this operation — for example an API key whose action or library scope excludes it, or a credential type this operation does not accept.
- `404` — Not found
- `422` — Validation Error
- `429` — Rate limit exceeded. Retry after the interval in the `Retry-After` header.

---

[API](https://skmtc.net/gumnut-ai/apis/gumnut-api.md) · [All operations](https://skmtc.net/gumnut-ai/apis/gumnut-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/gumnut-ai/gumnut-api/revisions/bf08b1e1d8bd/schema)
