---
description: Read and write FHIR Binary resources as JSON or as raw binary content on the /fhir/Binary endpoints.
---

> For the complete documentation index, see [llms.txt](https://staging.health-samurai.io/docs/aidbox/llms.txt).
> Use it to discover all available pages before guessing URLs.

---

# Binary resource

{% hint style="info" %}
This functionality is available starting from Aidbox version **2607**.
{% endhint %}

The FHIR [Binary](https://www.hl7.org/fhir/binary.html) resource carries raw content such as documents and images: a `contentType` and the base64-encoded `data`. Aidbox follows the [FHIR rules for handling Binary resources over REST](https://www.hl7.org/fhir/binary.html#rest): the same endpoint returns the resource as JSON or as the decoded content, and accepts raw uploads without a JSON wrapper.

## Create and update

`POST /fhir/Binary` and `PUT /fhir/Binary/{id}` accept two kinds of body:

* A Binary resource as JSON (`Content-Type: application/fhir+json`, `application/json`, or `json`): a regular create or update.
* Any other content type: Aidbox builds the Binary itself. `contentType` comes from the `Content-Type` header and the body bytes go base64-encoded into `data`.

{% tabs %}
{% tab title="Request" %}
```http
POST /fhir/Binary
Content-Type: application/octet-stream

hello world
```
{% endtab %}

{% tab title="Response" %}
```json
{
  "resourceType": "Binary",
  "id": "b9f7a86e-16a5-45f5-8b1c-3e2a90c31c02",
  "contentType": "application/octet-stream",
  "data": "aGVsbG8gd29ybGQ="
}
```
{% endtab %}
{% endtabs %}

A JSON body without `"resourceType": "Binary"` is stored as binary content too: the JSON text becomes `data` and the request content type becomes `contentType`.

With `Prefer: return=minimal`, Aidbox returns an empty body with the `Location` header.

## Read

`GET /fhir/Binary/{id}` returns the decoded content when the `Accept` header contains the type stored in `Binary.contentType`. Aidbox decodes `data` and responds with the bytes under that content type:

{% tabs %}
{% tab title="Request" %}
```http
GET /fhir/Binary/b9f7a86e-16a5-45f5-8b1c-3e2a90c31c02
Accept: application/octet-stream
```
{% endtab %}

{% tab title="Response" %}
```
hello world
```
{% endtab %}
{% endtabs %}

The JSON content types are the one exception. When `Accept` contains `application/fhir+json` (or `application/json` and `json`, which Aidbox keeps for backward compatibility), Aidbox returns the Binary resource itself as FHIR JSON with base64 `data`, whatever `Binary.contentType` holds. A request without an `Accept` header gets the resource as well.

Any other `Accept` value gets `406` with an `OperationOutcome`.

The `_format` query parameter overrides `Accept` and takes the same values. When `_format` names a non-JSON content type that differs from `Binary.contentType`, Aidbox responds with `422`.

Version read, `GET /fhir/Binary/{id}/_history/{vid}`, negotiates the same way and serves the content of the requested version.

## Data offload

`Binary.data` can live in external blob storage instead of PostgreSQL, with reads, including raw reads, working unchanged:

{% content-ref %}
[Offload base64Binary data to external storage](../../../configuration/storage-and-api-configuration/offload-base64binary-to-external-storage.md)
{% endcontent-ref %}

### Streaming large files

{% hint style="info" %}
Streaming is available starting from Aidbox version **2608**.
{% endhint %}

With offload configured for the `data` element, Aidbox streams raw content between the client and the blob storage:

* On raw upload, Aidbox copies the request body to the storage as it arrives, without the base64 round-trip and without buffering the whole payload.
* On raw read, Aidbox pipes the blob from the storage into the response.

Only a small buffer stays in memory at any moment, so you can upload and download files larger than the memory available to the Aidbox instance. The request body limit still applies to uploads: Aidbox rejects bodies over the [`web.max-body`](../../../reference/all-settings.md#web.max-body) setting with `413`. The default is 20 MB, raise it to accept larger files.

Streaming covers raw content only. A Binary posted as FHIR JSON carries `data` as a base64 string, and a JSON read returns it the same way, so Aidbox handles the whole payload in memory on these paths.
