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

# Blob Storage API quickstart

> Upload and download your first file with the Blob Storage API: the v1 base URL, the Authorization header, a curl upload, its response and a download link.

Blob Storage keeps your files, serves public ones from a CDN and hands out links to private ones. This page takes you from an API key to an uploaded file and a download link, with `curl`. Storage is included in every plan: see [Blob Storage](/en/services/blob) for the plans, prices and FAQ.

## Base URL

Every endpoint of this reference is relative to:

```bash theme={"system"}
https://blob.squarecloud.app/v1
```

## Authentication

Blob Storage takes the same API keys as the [Square Cloud API](/en/api-reference/introduction), in the `Authorization` header. The key needs the `blob:write` scope to upload and `blob:read` to list and download, and it can't be restricted to specific applications. Create one in your [account security settings](https://squarecloud.app/en/account/security) and keep it in an environment variable:

```bash theme={"system"}
export SQUARECLOUD_API_KEY="your-api-key"
```

More on scopes and upload tokens in [Authentication](/en/blob-reference/authentication).

## Upload a file

[Object Post](/en/blob-reference/endpoint/post) takes the file as `multipart/form-data` and its name, without extension, in the query:

```bash theme={"system"}
curl --request POST \
  --url 'https://blob.squarecloud.app/v1/objects?name=logo&prefix=images' \
  --header "Authorization: $SQUARECLOUD_API_KEY" \
  --form 'file=@./logo.png'
```

```json theme={"system"}
{
  "status": "success",
  "response": {
    "id": "pub/3155597145698959364/images/logo.png",
    "private": false,
    "url": "https://blob.squarecloud.dev/pub/3155597145698959364/images/logo.png",
    "size": 416230,
    "name": "logo",
    "prefix": "images",
    "sha256": "5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
    "replaced": false
  }
}
```

The file is public by default: `url` works right away in a browser or an `<img>` tag. Store the `id` as it comes, since every other route takes it.

A single request takes files from 512 bytes to 100 MB. Larger files, up to 10 GiB, go through the [chunked upload](/en/blob-reference/endpoint/chunked-init) or the [S3 gateway](/en/blob-reference/s3-compatibility).

## Upload a private file

Add `private=true` and the file gets no public URL (`url` is `null`):

```bash theme={"system"}
curl --request POST \
  --url 'https://blob.squarecloud.app/v1/objects?name=invoice&prefix=invoices&private=true' \
  --header "Authorization: $SQUARECLOUD_API_KEY" \
  --form 'file=@./invoice.pdf'
```

## Download a file

A public file downloads from its `url`. For a private one, [Object Download](/en/blob-reference/endpoint/download) signs a temporary link that works without credentials, and redirects to it, so `curl -L` saves the file:

```bash theme={"system"}
curl -L --output invoice.pdf \
  --url 'https://blob.squarecloud.app/v1/objects/download?object=<id>' \
  --header "Authorization: $SQUARECLOUD_API_KEY"
```

Replace `<id>` with the `id` of the upload. Add `redirect=false` to get the link as JSON and hand it to someone else. For links you can revoke or protect with a password, create a [share link](/en/blob-reference/endpoint/shares-create).

## List and delete files

[Object List](/en/blob-reference/endpoint/list) returns your files page by page:

```bash theme={"system"}
curl --url 'https://blob.squarecloud.app/v1/objects?prefix=images/' \
  --header "Authorization: $SQUARECLOUD_API_KEY"
```

[Objects Delete](/en/blob-reference/endpoint/delete) removes one file, or up to 100 in one request:

```bash theme={"system"}
curl --request DELETE \
  --url 'https://blob.squarecloud.app/v1/objects' \
  --header "Authorization: $SQUARECLOUD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{ "object": "<id>" }'
```

## When something fails

Errors come as `{ "status": "error", "code": "..." }`. The ones you are most likely to meet first:

| Code | HTTP | Fix |
| - | - | - |
| `ACCESS_DENIED` | 401 | The key is missing or not recognized. Check the `Authorization` header. |
| `PERMISSION_DENIED` | 401 | The account has no active plan, so it can't upload. |
| `MISSING_SCOPE` | 403 | The key lacks `blob:write` or `blob:read`. Create a key with that scope. |
| `RESOURCE_NOT_ALLOWED` | 403 | The key is restricted to applications. Use a key without that restriction. |
| `FILE_TOO_LARGE` | 413 | The file is over 100 MB. Use the chunked upload. |

Every code is in [Errors](/en/blob-reference/errors).

## Next steps

<CardGroup cols={2}>
  <Card title="Blob SDK" icon="js" href="/en/sdks/blob/client">
    Upload and manage files from JavaScript, with chunked uploads handled for you.
  </Card>

  <Card title="S3 compatibility" icon="bucket" href="/en/blob-reference/s3-compatibility">
    Use aws-cli, boto3, rclone or any AWS SDK.
  </Card>

  <Card title="Links and sharing" icon="share-nodes" href="/en/blob-reference/links-and-sharing">
    Temporary links, share links and when to use each.
  </Card>

  <Card title="Upload from the browser" icon="upload" href="/en/blob-reference/endpoint/upload-tokens">
    Let visitors upload without exposing your API key.
  </Card>
</CardGroup>
