> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/deployment/monitoring-and-analytics/vision-events/upload-a-vision-event-bundle.md).

# Upload a Vision Event Bundle

## About

The [Write Vision Event Bundle](https://docs.roboflow.com/workflows/blocks/blocks/data-storage/vision-event-bundle) block writes one tarball per event to local disk instead of sending it to Roboflow. Use it when your inference server runs in a network with no route to the cloud. This endpoint takes those tarballs as they are: your uploader posts each file, and Roboflow unpacks it, uploads the images, and creates the [Vision Event](/deployment/monitoring-and-analytics/vision-events.md).

## HTTP API

Post the raw archive bytes as the request body. Do not use JSON or multipart. The body is binary, so send your API key in the `Authorization: Bearer` header or in the `api_key` query parameter.

**Required scope:** `vision-events:write` or `device:update`

{% openapi src="/files/sCDP9kVopV4JkkRK7GDd" path="/vision-events/bundle" method="post" %}
[openapi.yaml](https://1583372177-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-2afefc06c784ca78eb7ec96a99bee48f8a2daaa5%2Fopenapi.yaml?alt=media)
{% endopenapi %}

### Bundle Format

Each bundle holds one event. The block writes gzipped tar files, and plain tar also works.

```
event_<timestamp>_<eventId>.tar.gz
├── payload.json
└── images/<file_id>.jpg
```

`payload.json` has the same shape as the [Create a Vision Event](/deployment/monitoring-and-analytics/vision-events/create-a-vision-event.md#request-body-parameters) request body, with two differences:

* `bundleFormatVersion` is `1`.
* `images[].file` and `images[].inputFile` hold archive member paths (ex: `images/9f0c1b2a.jpg`) in place of `sourceId` and `inputSourceId`. Roboflow uploads each member and stores the source IDs on the event.

Images must sit under the `images/` directory. Members that no image refers to, and top-level directories other than `images/`, add an ingestion warning but do not stop the event.

Field errors inside `payload.json` behave the same as on the JSON endpoint. See [Validation and Warnings](/deployment/monitoring-and-analytics/vision-events/create-a-vision-event.md#validation-and-warnings).

### Use Case

The `useCaseId` query parameter overrides the `useCaseId` in `payload.json`. If neither one is set, the request fails with a 400. Air-gapped sites normally leave the use case out of the bundle, so no cloud identifiers are stored inside the local network, and set it at upload time instead.

### Limits

<table data-search="false"><thead><tr><th>Limit</th><th>Value</th><th>Status on failure</th></tr></thead><tbody><tr><td>Request body</td><td>25 MB</td><td>413</td></tr><tr><td>Decompressed archive</td><td>75 MB</td><td>413</td></tr><tr><td><code>payload.json</code></td><td>10 MB</td><td>413</td></tr><tr><td>Archive entries</td><td>217</td><td>413</td></tr><tr><td>Images per bundle</td><td>100</td><td>400</td></tr><tr><td>Pixels per image</td><td>80 MP</td><td>413</td></tr></tbody></table>

### Retries

You can post the same bundle again after a failed or unclear upload. Images are matched by content, and an event that arrives twice replaces the earlier one. You are billed one time for it.
