> For the complete documentation index, see [llms.txt](https://docs.unitlab.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.unitlab.ai/api-sdk-cli/apis/releases-api.md).

# Releases API

Create versioned annotation exports, scope them by Batch Queue or data type, and understand review and S3 delivery limits.

{% hint style="info" %}
**Outcome:** Create versioned Project exports, inspect metadata, and request annotation or source downloads.
{% endhint %}

A Release freezes eligible annotation data from a Project for download. It is not an approval filter. A release's `ready` status means export preparation finished, not that a reviewer accepted every included label.

## Endpoints

| Method | Endpoint                                   | Purpose                                                                               |
| ------ | ------------------------------------------ | ------------------------------------------------------------------------------------- |
| GET    | `/api/sdk/releases/`                       | List Releases                                                                         |
| GET    | `/api/sdk/releases/{release_id}/`          | Retrieve Release metadata                                                             |
| POST   | `/api/sdk/projects/{project_id}/releases/` | Create a Project snapshot                                                             |
| POST   | `/api/sdk/releases/{release_id}/`          | Prepare an annotation or source download                                              |
| GET    | `/api/sdk/releases/{release_id}/status/`   | Check asynchronous preparation when the server returns a pending or exporting Release |

## Walkthrough: create and download a release

### 1. Prepare the delivery and request values

Verify the required reviews for every eligible item in the selected Project or Batch Queue before starting. See [Export only reviewed work](#export-only-reviewed-work). This example creates a COCO image release with an 80/20 train/validation split.

Use your [configured API key](https://docs.unitlab.ai/api-sdk-cli/get-started/authentication-and-configuration). Set the API base URL in your shell:

```bash
export UNITLAB_API_URL="https://api.unitlab.ai"
```

Replace `PROJECT_ID` and `BATCH_QUEUE_ID` below with real UUIDs. Keep `UNITLAB_API_KEY` in your configured environment. The HTTP API uses `generic_types: ["img"]` for images; the Python SDK translates `data_types=["image"]` to this value.

### 2. Create the release

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$UNITLAB_API_URL/api/sdk/projects/PROJECT_ID/releases/" \
  -H "Authorization: Api-Key $UNITLAB_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "export_type":"COCO",
    "split_ratios":{"train":80,"validation":20},
    "include_download_tokens":false,
    "upload_sessions":["BATCH_QUEUE_ID"],
    "generic_types":["img"]
  }'
```

![Project release configuration dialog](https://292810646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGjVLUz4wthGkGlRKM6rM%2Fuploads%2FHLzEBrP9ddsrTUbQ4ovz%2Frelease-create-modal.png?alt=media\&token=70baced4-91a7-4c40-bf7b-417177d75b90)

*The request selects Batch Queues, data types, formats, split distribution, and download-token policy. Batch Queue selection does not filter for review approval.*

### 3. Save its ID and check preparation

Retain the returned `pk` as `RELEASE_ID`. Read that release back and verify its version, item count, data type, formats and visibility:

```bash
curl --fail-with-body --silent --show-error \
  "$UNITLAB_API_URL/api/sdk/releases/RELEASE_ID/" \
  -H "Authorization: Api-Key $UNITLAB_API_KEY"
```

If its status is `pending` or `exporting`, check the same release's preparation:

```bash
curl --fail-with-body --silent --show-error \
  "$UNITLAB_API_URL/api/sdk/releases/RELEASE_ID/status/" \
  -H "Authorization: Api-Key $UNITLAB_API_KEY"
```

Repeat the status check at bounded intervals, inspecting `release_status` until it is `ready` or `failed`. The status endpoint's separate top-level `status` uses `processing`, `completed`, or `failed`. A timeout does not cancel server preparation: retain this ID rather than immediately creating another release. Older servers can return a completed Release without a status field; do not require a status endpoint on those servers.

### 4. Request the annotation download

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$UNITLAB_API_URL/api/sdk/releases/RELEASE_ID/" \
  -H "Authorization: Api-Key $UNITLAB_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"download_type":"annotation","split_type":"train"}'
```

The annotation response contains a temporary URL in `file`. Retrieve that URL to download the artifact; the POST response itself is download metadata. Request only a populated split. Omit `split_type` to request a combined bundle of all populated splits.

To obtain source files separately, use the same endpoint with `{"download_type":"files"}`. File downloads can return inline content or per-file URLs. Keep signed URLs private and validate local destination paths.

### 5. Validate the downloaded delivery

Open the annotation file or archive, inspect sample labels, and compare represented item IDs and counts with your verified delivery scope. Check train/validation membership and the consumer's required schema. Keep the release ID and version with the artifact.

## Export only reviewed work

The create request accepts `upload_sessions` for Batch Queue IDs and `generic_types` for data types. It does not accept an `approved_only`, Review stage, or arbitrary item-ID filter; its only workflow-status filter is `completed_only` (below). Eligibility uses the latest valid annotations with active classes in the selected scope, including unreviewed labels if they are otherwise eligible.

For an approved delivery, use a dedicated Project or Batch Queue whose entire eligible contents have completed the required review. Verify approval decisions using [Workflow task timelines](/api-sdk-cli/apis/annotations-and-workflow-api.md), keep that scope unchanged while the export snapshot is prepared, and reconcile the exported item identifiers and counts. The snapshot captures the latest eligible annotation history when it is frozen; it is not a request to recover the last approved revision of every item.

If reviewed and unreviewed items are mixed in the same scope, there is no single approved-only release request. Prepare an independently controlled delivery scope or filter a downloaded export in your own pipeline after checking review evidence. Do not present a broad project export as approved-only.

### Release only completed items

Add `"completed_only": true` to the create request:

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$UNITLAB_API_URL/api/sdk/projects/PROJECT_ID/releases/" \
  -H "Authorization: Api-Key $UNITLAB_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"export_type":"UUEF","split_ratios":{"train":100},"completed_only":true}'
```

The release then contains only the items whose current workflow status is **Complete** (for a Data Group, the group's own status), with their latest labels. In the Python SDK (3.1.2 and later), pass `completed_only=True`.

{% hint style="warning" %}
This filter checks the status at the moment the release is created. It does not prove that an item was reviewed or approved: an item can reach Complete through a route that has no Review stage.
{% endhint %}

* If no completed item has annotations, the request is refused with "No completed items with annotations to release."
* The response echoes `"completed_only": true`. A response without it comes from a server that does not support the option and released every eligible item. The Python SDK checks this and raises an error (`completed_only_unsupported`).
* The option is available in the SDK and the API only. The release dialog in the web app and the CLI do not have it.

## S3 export destination

For cloud-backed media, generated annotation exports can be written to the saved source cloud connection. For a project using one S3 connection, that means the source bucket under the connection's configured prefix and Unitlab's generated release path. The connection needs permission to write there.

The create and download requests do not accept a destination bucket, connection, or object key. If a Release includes sources from several cloud connections, the backend selects the first source connection represented in the release; callers cannot select it through this API. Use one source connection when the native destination must be predictable. See [Cloud storage](/api-sdk-cli/sdks/cloud-storage.md) for storage behavior and permissions.

For a different destination bucket or a specific object name, download the annotation artifact and upload it with your own AWS tooling. This is a client-side transfer, not a Unitlab export destination option.

***

> **Explore related Unitlab capabilities:** [multimodal data curation](https://unitlab.ai/en/data-curation)
