> ## Documentation Index
> Fetch the complete documentation index at: https://www.spacebring.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# File uploads

> Upload images and files through the Spacebring API and attach them to events and other objects

Files never pass through the Spacebring API. You ask the API for an upload, send the file bytes straight to storage, then reference the file when you create or update the object it belongs to.

## Upload a file

1. **Create the upload.** Call the upload endpoint of the object you are working with and declare the file's `mimeType` and exact `size` in bytes. The response carries a `key` and an `upload` block with a presigned URL.

   ```json theme={null}
   {
     "media": {
       "key": "1757585000-6ba7b810-9dad-41d1-80b4-00c04fd430c8",
       "mimeType": "image/jpeg",
       "size": 248113,
       "status": "pending",
       "upload": {
         "method": "PUT",
         "url": "https://…amazonaws.com/1757585000-6ba7b810-…?X-Amz-Signature=…",
         "headers": { "Content-Type": "image/jpeg", "Content-Length": "248113" },
         "expirationDate": "2026-09-11T10:31:00.000Z"
       }
     }
   }
   ```

2. **Send the file.** Make a `PUT` request to `upload.url` with the raw file bytes as the body and exactly the `upload.headers` returned. Do not send a multipart form and do not add your Spacebring credentials. Storage rejects the request when the size or type differs from what you declared, or when the URL has passed its `expirationDate`.

   ```bash theme={null}
   curl -X PUT "$UPLOAD_URL" \
     -H "Content-Type: image/jpeg" \
     -H "Content-Length: 248113" \
     --data-binary @cover.jpg
   ```

3. **Attach the file.** Pass the `key` on the create or update request of the object. For an event, set `media[0].key`. The object response then carries the public `url` of the file.

<Warning>
  The upload URL is valid for 60 seconds and the key for one hour. A file that is not attached to an object within the hour is deleted.
</Warning>

## Errors

* Creating an upload with an unsupported `mimeType` or a `size` above the limit returns `400` with a `validationError` naming the field.
* Attaching a key whose file has not reached storage yet returns `409` with the code `fileUploadPending`. Wait for the `PUT` request to finish and retry.
* Attaching a key that is unknown, expired, or created by another network returns `400` with the code `fileUploadNotFound`. Create a new upload.

In both cases the object is not created or updated. Branch on `code` in the response body, not on the message.

## Upload endpoints

Each object type that accepts files has its own upload endpoint and its own limits.

| Object | Create upload                                                        | Types                | Max size |
| :----- | :------------------------------------------------------------------- | :------------------- | :------- |
| Event  | [Create a media upload](/docs/api-reference/events/create-a-media-upload) | JPEG, PNG, WebP, GIF | 5 MB     |
