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

# S3-compatible storage

The io.b3os/s3 pack: 6 actions with call snippets, fixture outputs, connection setup and error codes, generated from version 1.0.0.

`io.b3os/s3` 1.0.0 · `storage`, `files`, `open-data` · MIT

Read and write objects in S3-compatible storage (AWS S3, Cloudflare R2, DigitalOcean Spaces, Backblaze B2, Wasabi, Linode, Google Cloud Storage) through presigned URLs you generate with your own keys, and read public AWS buckets by name (open data such as NOAA). Objects come back as text, or parsed JSON for JSON objects; binary objects are not supported. No access keys are stored: this pack cannot sign requests.

Every call's result carries `upstream_status` and `timing`: `validate_ms`, `inject_ms`, `render_ms`, `upstream_ms`, `map_ms` and `total_ms`. `upstream` is the service's time; the others are B3OS's own ([call actions](/actions/call)). The snippets below show no timing values, because a fixture records none.

## Connection

No credential: a keyless public API. Calls name no connection.

Hosts it reaches: `*.amazonaws.com`, `*.r2.cloudflarestorage.com`, `*.r2.dev`, `*.digitaloceanspaces.com`, `*.backblazeb2.com`, `*.wasabisys.com`, `*.linodeobjects.com`, `storage.googleapis.com`.

## Actions

| Action | Effect | MCP tool | Title |
|---|---|---|---|
| [`get-object`](/actions/catalog/s3#s3-get-object) | read | `s3__get-object` | Get object (URL) |
| [`head-object`](/actions/catalog/s3#s3-head-object) | read | `s3__head-object` | Get object metadata (URL) |
| [`put-object`](/actions/catalog/s3#s3-put-object) | write | `s3__put-object` | Upload object (presigned URL) |
| [`delete-object`](/actions/catalog/s3#s3-delete-object) | irreversible | `s3__delete-object` | Delete object (presigned URL) |
| [`get-public-object`](/actions/catalog/s3#s3-get-public-object) | read | `s3__get-public-object` | Get public object (AWS) |
| [`list-public-objects`](/actions/catalog/s3#s3-list-public-objects) | read | `s3__list-public-objects` | List public bucket (AWS) |

get-object

**Get object (URL).** Download a text or JSON object from a presigned GET URL or a public object URL, with its content type, size, ETag and Last-Modified.

Ref `io.b3os/s3/get-object@1.0.0` · effect `read` · no connection · MCP tool `s3__get-object`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/s3/get-object@1",
          "input": {"url": "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-version.txt"}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/s3/get-object@1",
      input: { url: "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-version.txt" },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/s3/get-object@1",
        "input": {
            "url": "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-version.txt",
        },
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "s3__get-object",
        "arguments": {
          "url": "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-version.txt"
        }
      }
    }
    ```

    Expose the pack as tools with `--packs s3` on the local server or `?packs=s3` on the remote URL, and the agent calls `s3__get-object` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Get object (URL) (response recorded 2026-10-26). From the bundle's `fixtures/get-object.json`, not a live call.

```json
{
  "status": 200,
  "content_type": "application/octet-stream",
  "content_length": "270",
  "etag": "\"ce4b95c54fb467188f7cd0f8704193e7\"",
  "last_modified": "Mon, 26 Oct 2026 03:04:41 GMT",
  "body": "The current version of GHCN Daily is 3.35-upd-2026102417 (i.e, an update that started at 2026102417 [yyyymmddhh] UTC; yyyy=year; mm=month; dd=day; hh=hour),\ncreated by appending recently available data updates to the last fully reprocessed version: 3.35-por-2026101623.\n"
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | No such bucket or key (or the bucket does not allow listing). |
| `forbidden` | 403 | no | Access denied: the object is not public, or the presigned URL expired, was signed for another method or has a mismatched Content-Type. |
| `invalid_request` | 301, 307, 400, 412 | no | The bucket is in another region; use its regional endpoint URL. |
| `rate_limited` | 429, 503 | yes | Object storage asked to slow down (SlowDown). |

head-object

**Get object metadata (URL).** Content type, size, ETag and Last-Modified of an object from a presigned HEAD URL or a public URL, without downloading it. Use it to check that an object exists.

Ref `io.b3os/s3/head-object@1.0.0` · effect `read` · no connection · MCP tool `s3__head-object`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/s3/head-object@1",
          "input": {
            "url": "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-countries.txt"
          }
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/s3/head-object@1",
      input: {
        url: "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-countries.txt",
      },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/s3/head-object@1",
        "input": {
            "url": "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-countries.txt",
        },
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "s3__head-object",
        "arguments": {
          "url": "https://noaa-ghcn-pds.s3.amazonaws.com/ghcnd-countries.txt"
        }
      }
    }
    ```

    Expose the pack as tools with `--packs s3` on the local server or `?packs=s3` on the remote URL, and the agent calls `s3__head-object` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Get object metadata (URL) (response recorded 2026-10-26). From the bundle's `fixtures/head-object.json`, not a live call.

```json
{
  "status": 200,
  "content_type": "application/octet-stream",
  "content_length": "3659",
  "etag": "\"f1243f811af1949b11f1bce625b961b1\"",
  "last_modified": "Fri, 03 Feb 2023 22:32:30 GMT"
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | No such bucket or key (or the bucket does not allow listing). |
| `forbidden` | 403 | no | Access denied: the object is not public, or the presigned URL expired, was signed for another method or has a mismatched Content-Type. |
| `invalid_request` | 301, 307, 400, 412 | no | The bucket is in another region; use its regional endpoint URL. |
| `rate_limited` | 429, 503 | yes | Object storage asked to slow down (SlowDown). |

put-object

**Upload object (presigned URL).** Upload text (CSV, JSON, Markdown, logs, ...) to a presigned PUT URL, replacing any object at that key. If the URL was signed with a Content-Type, pass the same content_type. Returns the new ETag.

Ref `io.b3os/s3/put-object@1.0.0` · effect `write` · no connection · MCP tool `s3__put-object`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Idempotency-Key: 7c1e2f6a-1d43-4a8e-b2a5-3f0c9d5e8b11" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/s3/put-object@1",
          "input": {
            "url": "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-26.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000",
            "body": "date,orders\n2026-10-26,412\n",
            "content_type": "text/csv"
          }
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/s3/put-object@1",
      input: {
        url: "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-26.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000",
        body: "date,orders\n2026-10-26,412\n",
        content_type: "text/csv",
      },
    }, { idempotencyKey: crypto.randomUUID() });
    console.log(result.output);
    ```
  **Python**

```python
    import uuid
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/s3/put-object@1",
        "input": {
            "url": "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-26.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000",
            "body": "date,orders\n2026-10-26,412\n",
            "content_type": "text/csv",
        },
    }, idempotency_key=str(uuid.uuid4()))
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "s3__put-object",
        "arguments": {
          "url": "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-26.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000",
          "body": "date,orders\n2026-10-26,412\n",
          "content_type": "text/csv"
        }
      }
    }
    ```

    Expose the pack as tools with `--packs s3` on the local server or `?packs=s3` on the remote URL, and the agent calls `s3__put-object` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Upload object (presigned URL) (documented response shape, example values). From the bundle's `fixtures/put-object.json`, not a live call.

```json
{"status": 200, "etag": "\"9b2cf535f27731c974343645a3985328\""}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | No such bucket or key (or the bucket does not allow listing). |
| `forbidden` | 403 | no | Access denied: the object is not public, or the presigned URL expired, was signed for another method or has a mismatched Content-Type. |
| `invalid_request` | 301, 307, 400, 412 | no | The bucket is in another region; use its regional endpoint URL. |
| `rate_limited` | 429, 503 | yes | Object storage asked to slow down (SlowDown). |

delete-object

**Delete object (presigned URL).** Delete the object a presigned DELETE URL points to. S3 answers 204 whether or not the key existed.

Ref `io.b3os/s3/delete-object@1.0.0` · effect `irreversible` · no connection · MCP tool `s3__delete-object`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Idempotency-Key: 7c1e2f6a-1d43-4a8e-b2a5-3f0c9d5e8b11" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/s3/delete-object@1",
          "input": {
            "url": "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-25.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000"
          }
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/s3/delete-object@1",
      input: {
        url: "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-25.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000",
      },
    }, { idempotencyKey: crypto.randomUUID() });
    console.log(result.output);
    ```
  **Python**

```python
    import uuid
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/s3/delete-object@1",
        "input": {
            "url": "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-25.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000",
        },
    }, idempotency_key=str(uuid.uuid4()))
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "s3__delete-object",
        "arguments": {
          "url": "https://acme-reports.s3.us-east-1.amazonaws.com/daily/2026-10-25.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAEXAMPLE%2F20261026%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20261026T080000Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000"
        }
      }
    }
    ```

    Expose the pack as tools with `--packs s3` on the local server or `?packs=s3` on the remote URL, and the agent calls `s3__delete-object` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Delete object (presigned URL) (documented response shape, example values). From the bundle's `fixtures/delete-object.json`, not a live call.

```json
{"status": 204, "deleted": true}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | No such bucket or key (or the bucket does not allow listing). |
| `forbidden` | 403 | no | Access denied: the object is not public, or the presigned URL expired, was signed for another method or has a mismatched Content-Type. |
| `invalid_request` | 301, 307, 400, 412 | no | The bucket is in another region; use its regional endpoint URL. |
| `rate_limited` | 429, 503 | yes | Object storage asked to slow down (SlowDown). |

get-public-object

**Get public object (AWS).** Download a text or JSON object from a public AWS S3 bucket by bucket name and key, for example bucket noaa-ghcn-pds and key ghcnd-version.txt (AWS Open Data). Uses the bucket's global virtual-hosted endpoint.

Ref `io.b3os/s3/get-public-object@1.0.0` · effect `read` · no connection · MCP tool `s3__get-public-object`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/s3/get-public-object@1",
          "input": {"bucket": "noaa-ghcn-pds", "key": "ghcnd-version.txt"}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/s3/get-public-object@1",
      input: { bucket: "noaa-ghcn-pds", key: "ghcnd-version.txt" },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/s3/get-public-object@1",
        "input": {"bucket": "noaa-ghcn-pds", "key": "ghcnd-version.txt"},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "s3__get-public-object",
        "arguments": {"bucket": "noaa-ghcn-pds", "key": "ghcnd-version.txt"}
      }
    }
    ```

    Expose the pack as tools with `--packs s3` on the local server or `?packs=s3` on the remote URL, and the agent calls `s3__get-public-object` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Get public object (AWS) (response recorded 2026-10-26). From the bundle's `fixtures/get-public-object.json`, not a live call.

```json
{
  "status": 200,
  "content_type": "application/octet-stream",
  "content_length": "270",
  "etag": "\"ce4b95c54fb467188f7cd0f8704193e7\"",
  "last_modified": "Mon, 26 Oct 2026 03:04:41 GMT",
  "body": "The current version of GHCN Daily is 3.35-upd-2026102417 (i.e, an update that started at 2026102417 [yyyymmddhh] UTC; yyyy=year; mm=month; dd=day; hh=hour),\ncreated by appending recently available data updates to the last fully reprocessed version: 3.35-por-2026101623.\n"
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | No such bucket or key (or the bucket does not allow listing). |
| `forbidden` | 403 | no | Access denied: the object is not public, or the presigned URL expired, was signed for another method or has a mismatched Content-Type. |
| `invalid_request` | 301, 307, 400, 412 | no | The bucket is in another region; use its regional endpoint URL. |
| `rate_limited` | 429, 503 | yes | Object storage asked to slow down (SlowDown). |

list-public-objects

**List public bucket (AWS).** List keys in a public AWS S3 bucket (ListObjectsV2), optionally under a prefix and grouped by a delimiter such as /. Returns S3's ListBucketResult XML as text: Contents (Key, Size, LastModified, ETag), CommonPrefixes, IsTruncated and NextContinuationToken for the next page.

Ref `io.b3os/s3/list-public-objects@1.0.0` · effect `read` · no connection · MCP tool `s3__list-public-objects`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/s3/list-public-objects@1",
          "input": {"bucket": "noaa-ghcn-pds", "delimiter": "/", "max_keys": 3}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/s3/list-public-objects@1",
      input: { bucket: "noaa-ghcn-pds", delimiter: "/", max_keys: 3 },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/s3/list-public-objects@1",
        "input": {"bucket": "noaa-ghcn-pds", "delimiter": "/", "max_keys": 3},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "s3__list-public-objects",
        "arguments": {"bucket": "noaa-ghcn-pds", "delimiter": "/", "max_keys": 3}
      }
    }
    ```

    Expose the pack as tools with `--packs s3` on the local server or `?packs=s3` on the remote URL, and the agent calls `s3__list-public-objects` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: List public bucket (AWS) (response recorded 2026-10-26). From the bundle's `fixtures/list-public-objects.json`, not a live call.

```json
{
  "bucket": "noaa-ghcn-pds",
  "xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>noaa-ghcn-pds</Name><Prefix></Prefix><NextContinuationToken>1GVGTPA0SW8XTW9SRqMIbwN2TtACJKtuy4TBJIRiKxkkW+W9DRqJZIqPDoUgNVhdk</NextContinuationToken><KeyCount>3</KeyCount><MaxKeys>3</MaxKeys><Delimiter>/</Delimiter><IsTruncated>true</IsTruncated><Contents><Key>ghcnd-countries.txt</Key><LastModified>2023-02-03T22:32:30.000Z</LastModified><ETag>&quot;f1243f811af1949b11f1bce625b961b1&quot;</ETag><Size>3659</Size><StorageClass>STANDARD</StorageClass></Contents><CommonPrefixes><Prefix>csv.gz/</Prefix></CommonPrefixes><CommonPrefixes><Prefix>csv/</Prefix></CommonPrefixes></ListBucketResult>"
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | No such bucket or key (or the bucket does not allow listing). |
| `forbidden` | 403 | no | Access denied: the object is not public, or the presigned URL expired, was signed for another method or has a mismatched Content-Type. |
| `invalid_request` | 301, 307, 400, 412 | no | The bucket is in another region; use its regional endpoint URL. |
| `rate_limited` | 429, 503 | yes | Object storage asked to slow down (SlowDown). |