Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f5ce251
docs: add Walrus Console beta documentation
reemsabawi-mystenlabs Jul 13, 2026
9fd8972
docs: add Walrus Console to sidebar
reemsabawi-mystenlabs Jul 13, 2026
fc1d92f
docs: add Walrus Console to sidebar
reemsabawi-mystenlabs Jul 13, 2026
4bbe6c0
docs: address Console docs review feedback
reemsabawi-mystenlabs Jul 14, 2026
c568910
docs: apply Sui style-guide audit fixes to Console docs
reemsabawi-mystenlabs Jul 14, 2026
951f558
docs: use Prerequisites tab component in Console quickstart
reemsabawi-mystenlabs Jul 14, 2026
fe044de
docs: resolve remaining style-audit flags in Console docs
reemsabawi-mystenlabs Jul 15, 2026
47a9582
docs: source Console quickstart code from walrus-harbor-quickstart
reemsabawi-mystenlabs Jul 15, 2026
476d3fd
docs: address second-round Console docs review
reemsabawi-mystenlabs Jul 15, 2026
f40c791
docs(console): apply eng review corrections to beta availability claims
claude Jul 31, 2026
18c4be6
Merge remote-tracking branch 'origin/main' into reem/console-docs
claude Jul 31, 2026
b9933e3
docs(console): style-guide pass over the console pages
claude Jul 31, 2026
82b99db
docs(console): state the storage epoch duration and link the Network …
claude Aug 11, 2026
6146e44
Merge remote-tracking branch 'origin/main' into reem/console-docs
claude Aug 11, 2026
5975526
docs(console): active voice fixes flagged by the style gate
claude Aug 11, 2026
338575d
docs(console): cut the datasets asset type
claude Aug 12, 2026
b86f405
docs(console): add the Console FAQ for the beta launch
claude Aug 17, 2026
889800c
docs(console): active-voice fixes across the Console pages
claude Aug 17, 2026
a1e14dd
docs(console): correct the upload cap unit and firm up the free tier
claude Aug 18, 2026
60e183c
docs(console): the MCP server needs both Console keys, not just the A…
claude Aug 18, 2026
77acca3
docs(console): document the Console MCP server
claude Aug 18, 2026
6e9ecca
docs(console): point at the Console URLs and drop the alpha framing
claude Aug 19, 2026
40dcb11
docs(console): apply George's API-key flow review and reconcile the p…
claude Aug 19, 2026
f56b017
docs(console): name the API the Console developer API on the referenc…
claude Aug 19, 2026
91db174
docs(console): a plain API key reveals both secrets
claude Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
297 changes: 297 additions & 0 deletions docs/content/console/api-reference.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
---
title: API Reference
description: The Console developer API surface for spaces, buckets, files, and Seal sponsorship, including authentication, conventions, and error codes.
keywords: [walrus console, api reference, spaces, buckets, files, seal, api keys]
---

The Console developer API covers the endpoints third-party developers use to manage spaces, buckets, and files, plus the [Seal](/docs/data-security) sponsorship endpoints that back private-bucket access control.

:::info

The Console developer API is in beta at `https://api.console.walrus.xyz`. Endpoint shapes might change before GA. For a guided walkthrough of the full encrypted flow, start with the [Quick Start](./quickstart). For the product model behind these endpoints, see the [concepts and overview](./overview).

:::

## Authentication

Every request carries an API key as a bearer token:

```http
Authorization: Bearer hbr_…
```

Mint keys through the Console web interface. Each key has one of two roles:

1. `read_write` keys can change state: create and delete buckets, upload and delete files, and finalize private buckets.
2. `read_only` keys can list, check status, and download only. Any write with a read-only key returns `403` with code `read_only_api_key`.

A request with no valid key returns `401`. A key without access to the target resource returns `403`.

## Base URL and conventions

All paths are relative to the base URL and prefixed with `/api/v1`:

```
https://api.console.walrus.xyz
```

Request and response bodies are JSON unless noted (file upload uses `multipart/form-data`, and download returns a raw byte stream). Resource identifiers are UUIDs.

### Pagination

List endpoints return an opaque cursor. Pass `limit` to set page size and `cursor` to fetch the next page. When there are no further results, the cursor field returns `null`. Bucket lists return the cursor as `next_cursor`; file lists return it under `pagination.nextCursor`.

### Asynchronous operations

Console processes upload and delete operations asynchronously. Upload returns `202` with a file ID, then you poll the file status endpoint until the state is `completed`. Delete returns `204` immediately and releases storage after a background worker confirms the removal.

## Errors

Error responses use the shape:

```json
{ "error": "Human-readable message", "code": "machine_readable_code" }
```

The `code` field is present when a machine-readable value applies. Common error codes include:

| **Code** | **Meaning** |
| --- | --- |
| `unauthorized` | Missing or invalid API key. |
| `read_only_api_key` | A write was attempted with a read-only key. |
| `api_key_registering` / `api_key_revoking` / `api_key_revoked` | The key is not currently usable. |
| `bucket_not_in_scope` | The key cannot access the target bucket. |
| `bucket_not_finalized` | The bucket has not completed the finalize step. |
| `mirror_missing_grant` | The onchain access grant has not yet mirrored into the access index. Retry. |
| `quota_exceeded` | The operation exceeds the plan or storage quota. |
| `payload_too_large` | The upload exceeds the 100 MiB per-upload cap. |
| `bad_request` | The request failed validation. |
| `USED_NONCE` / `EXPIRED_TIMESTAMP` / `ADDRESS_MISMATCH` / `INVALID_CHALLENGE` | Wallet challenge errors, returned by the signature-authentication flow. |

Create-bucket requests that exceed a plan limit return `422` with a distinct shape:

```json
{ "code": "PLAN_LIMIT_EXCEEDED", "limit": "storage", "currentTier": "free" }
```

The `limit` value is one of `storage`, `users`, or `buckets`.

## Spaces

A space is the top-level container for your data. Console creates a Personal Space at sign-up.

### List spaces

`GET /api/v1/spaces`

Lists all spaces accessible to the authenticated user.

| **Parameter** | **Location** | **Required** | **Description** |
| --- | --- | --- | --- |
| `type` | query | No | Filter by space type: `personal` or `team`. |

Returns `200` with a `data` array of spaces. Each space includes `id`, `type`, `name`, `storage_used`, `storage_cap`, `bucket_count`, `role`, and `created_at`. Team Spaces also include `member_count`.

### List buckets in a space

`GET /api/v1/spaces/{id}/buckets`

| **Parameter** | **Location** | **Required** | **Description** |
| --- | --- | --- | --- |
| `id` | path | Yes | Space UUID. |
| `limit` | query | No | Page size, 1 to 1000. Default 100. |
| `cursor` | query | No | Cursor from a previous page. |
| `q` | query | No | Case-insensitive substring match on bucket name. |
| `visibility` | query | No | Filter by `public` or `private`. |
| `sortField` | query | No | `name`, `date`, or `storage`. Default `date`. |
| `sortOrder` | query | No | `asc` or `desc`. Default `desc`. |

Returns `200` with `buckets` and `next_cursor`.

### Create a bucket

`POST /api/v1/spaces/{id}/buckets`

Reserves a private bucket. This is the first step of the reserve, sign, and finalize handshake. In the current alpha, `scope` accepts `private` only.

Body:

```json
{ "name": "secrets", "scope": "private" }
```

Returns `201` with the reservation:

```json
{
"bucket_id": "…",
"bytes": "<base64 sponsored Sui transaction>",
"digest": "…",
"state": "pending_policy"
}
```

Sign `bytes` locally with your service key, then call the finalize endpoint. The bucket stays in `pending_policy` and accepts no uploads until finalize succeeds. A name conflict returns `409`. A plan-limit breach returns `422`. See the [Quick Start](./quickstart) for the full signing flow.

### List files in a space

`GET /api/v1/spaces/{id}/files`

Searches files across every bucket in the space.

| **Parameter** | **Location** | **Required** | **Description** |
| --- | --- | --- | --- |
| `id` | path | Yes | Space UUID. |
| `limit` | query | No | Page size, 1 to 100. Default 20. |
| `cursor` | query | No | Cursor from a previous page. |
| `q` | query | No | Case-insensitive substring match on file name. |
| `sortField` | query | No | `name`, `date`, `size`, or `type`. Default `date`. |
| `sortOrder` | query | No | `asc` or `desc`. Default `desc`. |

Returns `200` with `data` and a `pagination` object (`limit`, `hasMore`, `nextCursor`).

## Buckets

A bucket holds files inside a space. Private buckets store [Seal](/docs/data-security) ciphertext only.

### Get a bucket

`GET /api/v1/buckets/{id}`

Returns `200` with the bucket under `data`: `id`, `space_id`, `name`, `oyster_bucket_name`, `visibility`, `seal_policy_id`, `storage_used`, `created_at`, and `updated_at`.

### Update a bucket

`PUT /api/v1/buckets/{id}`

| **Field** | **Required** | **Description** |
| --- | --- | --- |
| `name` | Yes | New bucket name, 1 to 100 characters in length. |
| `sealPolicyId` | No | Seal policy ID. Pass `null` to clear. |
| `visibility` | No | Immutable in v1. Changing it returns `403`. |

Returns `200` with the updated bucket (`id`, `name`, `visibility`, `updated_at`). A name conflict returns `409`.

### Delete a bucket

`DELETE /api/v1/buckets/{id}?confirm=true`

Requires the `confirm=true` query parameter, and the bucket must be empty. Returns `204` with an `X-Deleted-Id` header. A missing confirmation, a validation error, or a non-empty bucket returns `400`.

### Finalize a private bucket

`POST /api/v1/buckets/{id}/finalize`

Submits the signature over the reserved transaction bytes to activate a pending private bucket.

Body:

```json
{ "signature": "<base64 signature>" }
```

Returns `200`:

```json
{ "bucket_id": "…", "seal_policy_id": "…", "state": "active" }
```

`seal_policy_id` is the onchain bucket-policy object ID used by Seal for access checks. You can now upload to the bucket.

### List files in a bucket

`GET /api/v1/buckets/{id}/files`

Takes the same `limit`, `cursor`, `q`, `sortField`, and `sortOrder` parameters as the space file listing. Returns `200` with `data` and `pagination`.

### Upload a file

`POST /api/v1/buckets/{id}/files`

Uploads a file asynchronously using `multipart/form-data`.

| **Field** | **Required** | **Description** |
| --- | --- | --- |
| `file` | Yes | The file bytes. For private buckets, upload the Seal-encrypted object. |
| `name` | No | File name, up to 255 characters in length. |
| `metadata` | No | JSON object string persisted with the file. Maximum 8 KiB. |

Returns `202` with the file summary under `data`. Poll the status endpoint until the state is `completed`.

:::info

After finalize, the onchain access grant takes a few seconds to propagate to the access index. During this window, uploads fail with a `403` and the error code `mirror_missing_grant`. Retry every few seconds until the grant appears.

:::

Other responses include `409` (bucket not finalized or duplicate file name), `413` (payload too large), `422` (quota exceeded), and `429` (rate limited).

## Files

File endpoints address a single file by ID: metadata, upload status, download, and delete.

### Get file metadata

`GET /api/v1/buckets/{id}/files/{fileId}`

Returns `200` with the file summary under `data`: `id`, `bucket_id`, `name`, `blob_id`, `oyster_object_id`, `size`, `mime_type`, `status`, `is_private`, `metadata`, `created_at`, `updated_at`, and `deleted_at`.

### Delete a file

`DELETE /api/v1/buckets/{id}/files/{fileId}`

Marks the file as `deleting` and enqueues a background job to remove the underlying blob. Returns `204` immediately. The worker releases storage after confirming the delete. Repeated calls for the same file ID are deduplicated.

### Get upload status

`GET /api/v1/buckets/{id}/files/{fileId}/status`

Polls the state of an in-flight upload after the upload endpoint returns `202`.

Returns `200` with `data.state`, one of `queued`, `active`, `completed`, or `failed`. When the worker reports it, `data.progress` gives fractional progress from 0 to 1. When the state is `failed`, `data.error` includes a `code` and `message`. Once the job leaves the queue this endpoint returns `404`, which does not mean the upload failed. If you get a `404` after uploading, check the file metadata endpoint to confirm the final status before treating it as an error.

### Download a file

`GET /api/v1/buckets/{id}/files/{fileId}/download`

Streams the raw file content with `Content-Type` and `Content-Disposition` headers. For a private bucket, this returns the Seal ciphertext, which you decrypt client-side. See the [Quick Start](./quickstart) for the decrypt flow.

A file in `deleting` or `deleted` status returns `423`. An unavailable blob stream returns `500`.

## Seal sponsorship

These endpoints build and sponsor the onchain bucket-policy transactions that manage private access. Console sponsors the gas through [Enoki](https://docs.enoki.mystenlabs.com/), so your service key signs but does not need a token balance. They are typically driven through the SDK patterns shown in the [Quick Start](./quickstart).

### Sponsor a transaction

`POST /api/v1/seal/sponsor`

Builds a sponsored bucket-policy transaction and returns the bytes to sign plus a digest to echo to the execute endpoint. The body's `kind` selects the operation:

| **`kind`** | **Purpose** | **Additional fields** |
| --- | --- | --- |
| `bucket_group_create` | Create a bucket access group. | `bucketId` |
| `grant_bucket_access` | Grant access to recipients. | `groupIds`, `recipientAddress`, `scope` (`read` or `readwrite`) |
| `share_admin` | Add an admin to a group. | `groupId`, `member` |
| `unshare` | Remove a member from a group. | `groupId`, `member` |
| `unshare_bucket_access` | Revoke a service signer's access. | `groupId`, `serviceSignerAddress` |

Returns `200` with `bytes` and `digest`.

### Execute a sponsored transaction

`POST /api/v1/seal/sponsor/{digest}/execute`

Submits the signature over the sponsored bytes. Console broadcasts the transaction and returns the onchain digest.

| **Parameter** | **Location** | **Required** | **Description** |
| --- | --- | --- | --- |
| `digest` | path | Yes | The sponsor digest from the sponsor endpoint. |

Body:

```json
{ "signature": "<base64 signature>" }
```

Returns `200` with the onchain `digest`. An expired or unknown digest returns `404`.
43 changes: 43 additions & 0 deletions docs/content/console/auth.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Authentication and Accounts
description: How Walrus Console sign-in works with Google and Apple through Sui zkLogin, how Console provisions your Pearl wallet, and how accounts stay separate per identity.
keywords: [walrus console, sign in, zklogin, pearl wallet, apple, google, accounts]
---

Walrus Console signs you in with the Google or Apple account you already have. There is no wallet to connect, no seed phrase to record, and no crypto setup: you sign in and start storing data.

:::info

Walrus Console is available on Mainnet through a closed, invite-only beta. It supports Google and Apple sign-in. For the product model, see the [concepts and overview](./overview).

:::

## How sign-in works

Console uses Sui [zkLogin](https://docs.sui.io/concepts/cryptography/zklogin). You authenticate with an identity provider you already have, and Console derives a [Sui address](https://docs.sui.io/concepts/cryptography/transaction-auth/keys-addresses) from that identity without exposing your provider account onchain and without asking you to manage a private key.

## Sign in with Google or Apple

1. Visit the [Walrus Console app](https://console.walrus.xyz/).
2. Choose **Continue with Google** or **Continue with Apple** and complete the provider sign-in.
3. Console provisions your account and a [Personal Space](./overview#core-concepts-spaces-buckets-and-files), then takes you to the dashboard.

Apple sign-in derives your Sui address from your Apple identity the same way. It accepts Apple's private email relay, so you can use the **Hide My Email** option.

## Your Pearl wallet

On first sign-in, Console silently provisions a Pearl wallet, the embedded wallet Console manages on your behalf, for your derived Sui address. This wallet holds the storage resources your data uses. Console manages the wallet and paying for transactions for you, so you do not need to fund it or sign transactions.

## Accounts stay separate per identity

:::warning

Each identity provider maps to a separate Console account and a separate Sui address. If you sign in with Google and later sign in with Apple, you get two independent accounts, not one merged account. Data stored under one is not visible under the other.

:::

Console shows an account-separation notice the first time you sign in so this is clear before you store anything. Choose one provider and use it consistently. Linking multiple providers to a single account is planned for a later release.

## Wallet sign-in

Signing in with an existing Sui wallet is planned for a later release. For now, sign in with Google or Apple through zkLogin. If you hold assets in a personal Sui wallet, note that data you store through Console lives under your zkLogin-derived address, which is separate from a wallet you connect later.
Loading
Loading