/v1/blobs
Upload and fetch binary blobs — the storage behind blob_ref experiences and media ingestion.
Authorization
bearer PASETO v4 public token (or deployment gate key). Auth-disabled dev instances accept any caller.
In: header
Request Body
*/*
TypeScript Definitions
Use the request body type in TypeScript.
binaryResponse Body
application/json
application/json
application/json
curl -X POST "https://example.com/v1/blobs" \ -H "Content-Type: */*" \ -d 'string'{ "blob_id": "string", "size_bytes": 0, "content_type": "string", "sha256": "string"}Authorization
bearer PASETO v4 public token (or deployment gate key). Auth-disabled dev instances accept any caller.
In: header
Path Parameters
blob_ id from the upload
Response Body
*/*
application/json
curl -X GET "https://example.com/v1/blobs/string""string"Authorization
bearer PASETO v4 public token (or deployment gate key). Auth-disabled dev instances accept any caller.
In: header
Path Parameters
Response Body
application/json
curl -X DELETE "https://example.com/v1/blobs/string"Upload
POST /v1/blobs takes the raw bytes as the request body (the body is the file). Response 200:
{ blob_id, size_bytes, content_type, sha256 } (the id key is blob_id, not id). The cap is 32 MiB
(33,554,432 bytes): one byte more returns 413.
Raw and JSON bodies are stored; multipart is rejected (415)
A raw body (any file type) or a Content-Type: application/json body is stored as the blob's bytes.
A multipart/form-data upload (e.g. curl -F file=@x) → 415 unsupported_media_type on v0.10.1
(note the lowercase code, an exception to the uppercase convention). Send the file as the raw body.
Same bytes ≠ same blob_id at the API
Uploading identical bytes twice returns two different blob_ids. Storage may deduplicate by
SHA-256 under the hood, but the API hands back a new id each time — don't rely on idempotent
blob_ids.
Idempotent upload (v0.9.10+, single-node only)
POST /v1/blobs/idempotent is a rollout-safe upload keyed by a client-persisted opaque token sent
as X-Cortex-Idempotency-Key: the exact same body bytes plus the canonicalised Content-Type replay
the authoritative blob_id; a different body under the same key → 409. DELETE /v1/blobs/idempotent
retires the upload by token even if the client never learned the blob_id.
Probe first: GET /v1/blobs/idempotent/status is a side-effect-free capability check that returns
protocol: keyed-blob-v1 even for an unknown token; without the header it is
422 INVALID_IDEMPOTENCY_KEY. A replay returns the same blob_id, different bytes under the same key
→ 409 IDEMPOTENCY_CONFLICT, and a retire answers status: "retired", bytes_deleted: true. An older server answers 404/405 without storing
the body, so clients should fail closed if the marker is absent. The plain POST /v1/blobs upload
above is unchanged.
Fetch and delete
GET /v1/blobs/{id}returns the exact bytes and echoes the uploadedContent-Type(no transcoding). It does not return aContent-Dispositionheader.DELETE /v1/blobs/{id}→200{ blob_id, bytes_deleted: true }; an unknown or already-deleted blob →404.
Blobs are deleted with the events made from them (v0.10.1)
An event captured from an uploaded text blob (content.kind: "blob_ref") records it in
source_blob_ids. Forgetting or erasing
that event deletes the blob too, unless another live event still uses it: the response reports
deleted.blobs: 1 (or retained_shared_blobs: 1 when it is kept), and a later GET or DELETE /v1/blobs/{id} answers 404, so treat that 404 as done. Events written before v0.10.1 carry no
link until an operator backfills it (POST /v1/admin/index-audit/source-blob-links; see
Admin). Capability erasure_blob_cascade_v1.
Text blobs must decode (v0.10.1)
Uploading is unchanged, but a capture that references a text blob whose bytes are neither UTF-8,
UTF-16 with a byte-order mark, nor valid in the declared charset= fails with 422 BLOB_TEXT_ENCODING_UNKNOWN instead of storing replacement characters. Upload non-UTF-8 text with its
charset (Content-Type: text/plain; charset=windows-1252). See
Experience.
Wiring blobs into memory
Reference an uploaded blob from an experience with content.kind: "blob_ref". A text blob is decoded
into the event's text with no extra setup (no content processors needed; it reads back as
content.kind: "text"). For a PDF, image, audio file or other binary blob, send its text in
content.transcript next to the blob_id: the event stores that text and recall searches it at once.
See Media ingestion for the full flow and the optional server-side
processors (Tika / vision / whisper).