# Upload a file to seal in an encrypted area

Uploads one or more files that you are going to encrypt, and returns their ids for
[Create an encrypted area](/api-reference/encrypted-areas/create)'s `file_ref`.

**Any file type is accepted** — an archive, a video, a key file, a file whose type your
browser could not determine. That is the difference between this endpoint and the general
[file upload](/api-reference/files/upload), which accepts documents, images and text only: the
general upload reads and indexes what you send it, so it has to understand the format. A file
uploaded here is **encrypted rather than read**, so there is nothing to understand.

> Nothing uploaded here is indexed, searchable, or used as assistant context. It exists to be
sealed.


Requires authentication (bearer token or API key), membership of the organization, and the
permission to create files. Send `multipart/form-data`.

**Encrypted areas are part of Conversations.** Where Conversations is switched off for your
account this endpoint answers `403`, exactly as the create endpoint does — there is no
arbitrary-file upload surface without the feature.

### Limits

| Limit | Value |
|  --- | --- |
| Files per request | 10 |
| Size per file | 100 MB |
| Request body | 1 GB (10 files plus multipart overhead) |


A file you intend to send as a **secure link** has a lower effective ceiling of **32 MB** —
that limit belongs to the seal, not to this upload, so an oversized file uploads here and is
refused with `413` when you create the area. See
[Create an encrypted area](/api-reference/encrypted-areas/create).

## Path parameters

**`organization_id`** string required

The organization the files belong to. You must be an active member of it.

## Body parameters

**`files`** file[] required

One to ten files, as `multipart/form-data` parts. Each part's declared content type is stored
as given when it is a valid media type, and recorded as `application/octet-stream` otherwise —
so a file your browser could not classify still uploads. The filename is stored for display and
travels **inside** the sealed area when you encrypt the file; it is never used as a storage
path.

## Returns

The same envelope as the general file upload, so one client parser serves both:

- `success` — `true` when every file stored.
- `message` — a short human-readable summary.
- `files` — the created file records; take `id` for `file_ref`.
- `total_uploaded`, `total_failed`.
- `errors` — one entry per failed file (`filename`, `error`, `mime_type`, `code`,
`file_size_bytes`), or `null`. **`error` is written to be shown to a person** — render it.


Status codes: `201` (all stored), `207` (some stored, some failed — read `errors`), `422` (all
failed for a non-size reason), `413` (all failed because they were too large, or the request
body exceeded the batch limit).

cURL

```bash
curl -X POST "https://api.aitronos.com/v1/organizations/org_123/files/encrypted-area-upload" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F "files=@./secrets.zip" \
  -F "files=@./id_rsa"
```

Python

```python
import requests

with open("secrets.zip", "rb") as archive:
    response = requests.post(
        "https://api.aitronos.com/v1/organizations/org_123/files/encrypted-area-upload",
        headers={"Authorization": f"Bearer {access_token}"},
        files={"files": ("secrets.zip", archive, "application/zip")},
        timeout=120,
    )
uploaded = response.json()["files"][0]

# Then seal it, with a note alongside it.
requests.post(
    "https://api.aitronos.com/v1/encrypted-areas",
    headers={"Authorization": f"Bearer {access_token}"},
    json={
        "audience": "link",
        "content_text": "The archive password is in our password manager.",
        "file_ref": uploaded["id"],
        "burn_after_read": True,
    },
    timeout=60,
)
```

JavaScript

```javascript
const form = new FormData();
form.append('files', file); // a File from an <input type="file"> or a drop

const response = await fetch(
  'https://api.aitronos.com/v1/organizations/org_123/files/encrypted-area-upload',
  { method: 'POST', headers: { Authorization: `Bearer ${accessToken}` }, body: form },
);
const result = await response.json();
if (result.total_failed > 0) {
  // Render this verbatim — it is written for the person who tried to upload.
  showError(result.errors[0].error);
}
const fileRef = result.files[0].id;
```

Response

```json 201 Created
{
  "success": true,
  "message": "Successfully uploaded 1 file(s)",
  "files": [
    {
      "id": "file_9f2c1d7a4b3e4f0a8c5d6e7f80912345",
      "original_filename": "secrets.zip",
      "mime_type": "application/zip",
      "file_size": 20480,
      "organization_id": "org_123"
    }
  ],
  "total_uploaded": 1,
  "total_failed": 0,
  "errors": null
}
```

Errors

```json 413 File too large
{ "success": false, "error": { "code": "FILE_TOO_LARGE", "message": "This file is larger than the 100 MB limit for an encrypted area.", "system_message": "This file is larger than the 100 MB limit for an encrypted area.", "type": "validation_error", "status": 413, "details": { "file_size_bytes": 209715200, "cap": 104857600 }, "trace_id": "...", "timestamp": "..." } }
```


```json 403 Not enabled
{ "success": false, "error": { "code": "FEATURE_DISABLED", "message": "This feature is not currently enabled for your organization.", "system_message": "Encrypted areas are not enabled for this account", "type": "authorization_error", "status": 403, "details": { "feature": "encrypted_area" }, "trace_id": "...", "timestamp": "..." } }
```


```json 422 Too many files
{ "success": false, "error": { "code": "INVALID_INPUT", "message": "An error occurred. Please try again.", "system_message": "Maximum 10 files per request", "type": "validation_error", "status": 422, "details": { "file_count": 11, "max_allowed": 10 }, "trace_id": "...", "timestamp": "..." } }
```

## Related Resources

- [Create an encrypted area](/api-reference/encrypted-areas/create) — seal the uploaded file.
- [Fetch a secure-link encrypted area](/api-reference/encrypted-areas/fetch-secure-link)
- [Fetch a recipient-bound encrypted area](/api-reference/encrypted-areas/fetch-recipient-bound)
- [Encrypted areas](/api-reference/encrypted-areas/introduction)