---
title: "Batch upload into a collection"
method: POST
path: "/v1/images/batch"
tags: ["Images"]
---

# Batch upload into a collection

`POST /v1/images/batch`

## Request

- Base URL: `https://api.pixelvault.dev`
- URL: `https://api.pixelvault.dev/v1/images/batch`
- Auth: HTTP bearer

Upload many images in one request, grouped into a collection (e.g. a CI run). Partial-failure tolerant: each item reports ok true/false independently. Private collections return signed URLs. The collection is upserted by (type, name), so re-running the same job is idempotent.

## Request body

- object
  - `collection` object, required
    - `type` string, required: Collection kind, e.g. ci_build.
    - `name` string: Idempotency key within (project, type) — e.g. the CI run id.
    - `visibility` 'public' | 'private'
    - `expires_in` integer: Image deletion TTL in seconds (60–2592000).
    - `sign_expires_in` integer: Signature lifetime for private URLs in seconds (60–2592000). Defaults to 7 days.
    - `metadata` object: Freeform collection metadata (e.g. commit, pr_number, branch).
  - `images` object[], required
    - `data` string: Base64-encoded image bytes.
    - `source_url` string: Public URL to import instead of data.
    - `filename` string
    - `metadata` object: Freeform image metadata (e.g. testName).

## Response `201`

Batch result (per-item ok/failure)

- object
  - `data` object
    - `collection_id` string
    - `items` object[]
      - `filename` string
      - `id` string
      - `url` string
      - `ok` boolean
      - `error` string

## Other responses

- `400`: Invalid request body
- `401`: Invalid or missing API key
- `402`: Free-plan private-image limit reached (upgrade for unlimited private images)

---

[API](https://skmtc.dev/pixelvault/apis/pixelvault-api.md) · [All operations](https://skmtc.dev/pixelvault/apis/pixelvault-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pixelvault/apis/pixelvault-api/revisions/6332d8c3f8e0?raw)
