# Client API: Object Storage: Buckets

> The 43 Client API operations for buckets.

Source: https://www.coritan.com/docs/api/reference/client/object-storage/object-storage-buckets/

Part of [Object Storage](/docs/api/reference/client/object-storage/).

## Operations

| Method | Path | Summary |
| --- | --- | --- |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets`](#op-get-api-v1-client-object-storage-service-id-buckets) | List buckets |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets`](#op-post-api-v1-client-object-storage-service-id-buckets) | Make a bucket in the chosen region, or the service's home region |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id) | Get bucket |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id) | Remove a bucket |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/cors`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-cors) | Get bucket cors |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/cors`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-cors) | Replace the bucket's CORS rules with the ones sent, at most 99 |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/cors`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-cors) | Remove every CORS rule from the bucket |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/domains`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-domains) | Link a custom domain to the bucket |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/domains/{hostname}`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-domains-hostnam) | Unlink a custom domain |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/domains/{hostname}/verify`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-domains-hostname) | Check a pending domain's DNS records now |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/encryption`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-encryption) | Get bucket encryption |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/encryption`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-encryption) | Turn default encryption on or off for the bucket |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle) | The bucket's lifecycle rules: what we delete from it, and when |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle) | Replace the bucket's lifecycle rules with the ones sent, at most 100 |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle) | Remove every lifecycle rule from the bucket, the default one included |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle/runs`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle-runs) | List lifecycle runs |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications) | The bucket's event notification rules, oldest first |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications) | Add a rule: POST each matching event in the bucket to url |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rule) | Change a rule |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-r) | Delete a rule |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}/deliveries`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rule) | The rule's deliveries of the last 30 days, newest first |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}/rotate-secret`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rul) | Replace the rule's signing secret and answer the new one, shown this once |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}/test`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rul) | Send test notification |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/object-lock`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-object-lock) | Get bucket object lock |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/object-lock`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-object-lock) | Change the default retention of a bucket with Object Lock |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-objects) | One page of the bucket under prefix, folders first |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-objects) | Delete named objects |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/details`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-details) | Get object details |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/legal-hold`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-legal-hold) | Put a legal hold on a version, or take it off |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/presign`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-presign) | A short-lived URL the browser uses directly for one GET, PUT or DELETE |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/restore`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-restore) | Restore object version |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/retention`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-retention) | Give a version a retention, or change the one it has |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/version`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-version) | Delete one version or delete marker for good |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/versions`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-versions) | List object versions |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/public`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-public) | Get public access |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/public`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-public) | Turn the bucket's public URL on or off |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/public/purge`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-public-purge) | Purge cache |
| GET | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication`](#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-replication) | The bucket's replication rules, the buckets a new rule may copy to, and the limits |
| POST | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication`](#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-replication) | Add replication rule |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication/{rule_id}`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-replication-rule-i) | Change a rule's prefix, turn replicated deletes on or off, or pause and resume it |
| DELETE | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication/{rule_id}`](#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-replication-rul) | Remove a rule |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/versioning`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-versioning) | Turn versioning on for a bucket, or suspend it |
| PUT | [`/api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/website`](#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-website) | Serve the bucket as a static website on its public URL and custom domains |

### List buckets {#op-get-api-v1-client-object-storage-service-id-buckets}

`GET /api/v1/client/object-storage/{service_id}/buckets`

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `service_id` | path | integer | yes |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `items` | array of BucketOut |  |
| `items[].id` | integer |  |
| `items[].name` | string |  |
| `items[].region` | string or null |  |
| `items[].location_id` | integer or null |  |
| `items[].location_name` | string or null |  |
| `items[].quota_bytes` | integer or null |  |
| `items[].used_bytes` | integer |  |
| `items[].object_count` | integer |  |
| `items[].usage_measured_at` | string or null |  |
| `items[].created_at` | string or null |  |
| `items[].deleted_at` | string or null |  |
| `items[].endpoint` | string or null |  |
| `items[].url` | string or null |  |
| `items[].cors_rules` | integer | How many CORS rules the bucket has |
| `items[].lifecycle_rules` | integer | How many lifecycle rules the bucket has |
| `items[].public_url` | string or null | The bucket's public URL while it is on, otherwise null |
| `items[].custom_domains` | integer | How many custom domains are linked to the bucket |
| `items[].versioning` | string, one of `off`, `enabled`, `suspended` | Whether the bucket keeps every version of its objects; once on, it is never off again |
| `items[].object_lock` | ObjectLockOut | A bucket's Object Lock and the default retention it gives new versions. |
| `items[].encryption` | boolean | True when objects written to the bucket are encrypted |
| `total` | integer |  |
| `bucket_prefix` | string |  |
| `max_buckets` | integer |  |

### Make a bucket in the chosen region, or the service's home region {#op-post-api-v1-client-object-storage-service-id-buckets}

`POST /api/v1/client/object-storage/{service_id}/buckets`

Make a bucket in the chosen region, or the service's home region.

``versioning`` keeps every version of every object from the start.
``object_lock`` creates the bucket with Object Lock, which you cannot add
later and which keeps versioning on for good; give it a ``mode`` and
``days`` or ``years`` for a default retention on every new version.
Answers 422 when the default retention is out of range.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `service_id` | path | integer | yes |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes |  |
| `location_id` | integer or null | no |  |
| `versioning` | boolean | no | Keep every version of every object. Object Lock turns this on whatever it says |
| `object_lock` | ObjectLockCreate or null | no | Create the bucket with Object Lock, which cannot be added later. Leave out for no lock |
| `object_lock.mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | no | The default retention's mode; leave out for a lock with no default retention |
| `object_lock.days` | integer or null | no | Default retention in days, from 1 to 36500 |
| `object_lock.years` | integer or null | no | Default retention in years, from 1 to 100, instead of days |
| `encryption` | boolean or null | no | Encrypt every object written to the bucket. Leave out to encrypt when default encryption is available. True while it is not available answers 409 |

#### Responses

| Status | Meaning |
| --- | --- |
| `201` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `201` response:

| Field | Type | Description |
| --- | --- | --- |
| `id` | integer |  |
| `name` | string |  |
| `region` | string or null |  |
| `location_id` | integer or null |  |
| `location_name` | string or null |  |
| `quota_bytes` | integer or null |  |
| `used_bytes` | integer |  |
| `object_count` | integer |  |
| `usage_measured_at` | string or null |  |
| `created_at` | string or null |  |
| `deleted_at` | string or null |  |
| `endpoint` | string or null |  |
| `url` | string or null |  |
| `cors_rules` | integer | How many CORS rules the bucket has |
| `lifecycle_rules` | integer | How many lifecycle rules the bucket has |
| `public_url` | string or null | The bucket's public URL while it is on, otherwise null |
| `custom_domains` | integer | How many custom domains are linked to the bucket |
| `versioning` | string, one of `off`, `enabled`, `suspended` | Whether the bucket keeps every version of its objects; once on, it is never off again |
| `object_lock` | ObjectLockOut | A bucket's Object Lock and the default retention it gives new versions. |
| `object_lock.enabled` | boolean | Whether the bucket was created with Object Lock |
| `object_lock.mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | The default retention's mode; null for no default retention |
| `object_lock.days` | integer or null | How long the default retention keeps each new version, in days |
| `object_lock.years` | integer or null | ``days`` in years, when it is a whole number of years |
| `encryption` | boolean | True when objects written to the bucket are encrypted |

### Get bucket {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}`

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `service_id` | path | integer | yes |
| `bucket_id` | path | integer | yes |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `id` | integer |  |
| `name` | string |  |
| `region` | string or null |  |
| `location_id` | integer or null |  |
| `location_name` | string or null |  |
| `quota_bytes` | integer or null |  |
| `used_bytes` | integer |  |
| `object_count` | integer |  |
| `usage_measured_at` | string or null |  |
| `created_at` | string or null |  |
| `deleted_at` | string or null |  |
| `endpoint` | string or null |  |
| `url` | string or null |  |
| `cors_rules` | integer | How many CORS rules the bucket has |
| `lifecycle_rules` | integer | How many lifecycle rules the bucket has |
| `public_url` | string or null | The bucket's public URL while it is on, otherwise null |
| `custom_domains` | integer | How many custom domains are linked to the bucket |
| `versioning` | string, one of `off`, `enabled`, `suspended` | Whether the bucket keeps every version of its objects; once on, it is never off again |
| `object_lock` | ObjectLockOut | A bucket's Object Lock and the default retention it gives new versions. |
| `object_lock.enabled` | boolean | Whether the bucket was created with Object Lock |
| `object_lock.mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | The default retention's mode; null for no default retention |
| `object_lock.days` | integer or null | How long the default retention keeps each new version, in days |
| `object_lock.years` | integer or null | ``days`` in years, when it is a whole number of years |
| `encryption` | boolean | True when objects written to the bucket are encrypted |

### Remove a bucket {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}`

Remove a bucket. Refused while it holds objects unless ``force`` is set.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes |  |
| `bucket_id` | path | integer | yes |  |
| `force` | query | boolean | no | Destroy the objects in it as well Default: `False`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type |
| --- | --- |
| `ok` | boolean |
| `bucket` | string |
| `region` | string or null |
| `objects_destroyed` | integer |

### Get bucket cors {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-cors}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/cors`

The bucket's CORS rules: which web pages on other sites may use it from
a browser, with which methods and headers.

An empty list means the bucket has no rules of its own. Browsers on any
site can then send it signed or presigned requests, and its public URL and
custom domains answer no other site. An S3 client that reads the bucket's CORS sees one more rule first,
``coritan-dashboard``, which lets the dashboard's file browser upload.
This list never holds it.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `rules` | array of CorsRule |  |
| `rules[].id` | string or null | A name for the rule, up to 255 characters. Optional. |
| `rules[].allowed_origins` | array of string | Origins whose pages may use the bucket, such as https://example.com. Each may hold one *, as in https://*.example.com; * alone allows every origin. |
| `rules[].allowed_methods` | array of string | Any of GET, PUT, POST, DELETE and HEAD |
| `rules[].allowed_headers` | array of string | Request headers the page may send, such as Content-Type. Each may hold one *. |
| `rules[].expose_headers` | array of string | Response headers the page may read, such as ETag. No *. |
| `rules[].max_age_seconds` | integer or null | How long a browser may keep the answer to its preflight request, in seconds |
| `max_rules` | integer |  |

### Replace the bucket's CORS rules with the ones sent, at most 99 {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-cors}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/cors`

Replace the bucket's CORS rules with the ones sent, at most 99.

The rules follow Amazon S3's: each needs at least one origin and one
method (GET, PUT, POST, DELETE or HEAD); an origin or an allowed header
may hold one ``*``; exposed headers hold none. A browser request uses the
first rule that matches its origin, method and headers. Answers 422 with
the rule at fault, 409 when the service is not active, and 429 after 60
rule changes in an hour. An empty list removes every rule, as DELETE does.
The rules apply within a minute.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `rules` | array of CorsRule | yes | Every rule the bucket should have, at most 99: S3 holds 100 and the dashboard keeps one so its file browser can upload. An empty list removes them all. |
| `rules[].id` | string or null | no | A name for the rule, up to 255 characters. Optional. |
| `rules[].allowed_origins` | array of string | yes | Origins whose pages may use the bucket, such as https://example.com. Each may hold one *, as in https://*.example.com; * alone allows every origin. |
| `rules[].allowed_methods` | array of string | yes | Any of GET, PUT, POST, DELETE and HEAD |
| `rules[].allowed_headers` | array of string | no | Request headers the page may send, such as Content-Type. Each may hold one *. |
| `rules[].expose_headers` | array of string | no | Response headers the page may read, such as ETag. No *. |
| `rules[].max_age_seconds` | integer or null | no | How long a browser may keep the answer to its preflight request, in seconds |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `rules` | array of CorsRule |  |
| `rules[].id` | string or null | A name for the rule, up to 255 characters. Optional. |
| `rules[].allowed_origins` | array of string | Origins whose pages may use the bucket, such as https://example.com. Each may hold one *, as in https://*.example.com; * alone allows every origin. |
| `rules[].allowed_methods` | array of string | Any of GET, PUT, POST, DELETE and HEAD |
| `rules[].allowed_headers` | array of string | Request headers the page may send, such as Content-Type. Each may hold one *. |
| `rules[].expose_headers` | array of string | Response headers the page may read, such as ETag. No *. |
| `rules[].max_age_seconds` | integer or null | How long a browser may keep the answer to its preflight request, in seconds |
| `max_rules` | integer |  |

### Remove every CORS rule from the bucket {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-cors}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/cors`

Remove every CORS rule from the bucket. Browsers on any site can then
send it signed or presigned requests, and its public URL and custom
domains answer no other site.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `rules` | array of CorsRule |  |
| `rules[].id` | string or null | A name for the rule, up to 255 characters. Optional. |
| `rules[].allowed_origins` | array of string | Origins whose pages may use the bucket, such as https://example.com. Each may hold one *, as in https://*.example.com; * alone allows every origin. |
| `rules[].allowed_methods` | array of string | Any of GET, PUT, POST, DELETE and HEAD |
| `rules[].allowed_headers` | array of string | Request headers the page may send, such as Content-Type. Each may hold one *. |
| `rules[].expose_headers` | array of string | Response headers the page may read, such as ETag. No *. |
| `rules[].max_age_seconds` | integer or null | How long a browser may keep the answer to its preflight request, in seconds |
| `max_rules` | integer |  |

### Link a custom domain to the bucket {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-domains}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/domains`

Link a custom domain to the bucket. A bucket takes up to 10.

When the domain is in a DNS zone this account holds on Coritan, we add
its ``CNAME`` record and the domain is verified at once. If the name
already has records in that zone, or is the zone's apex, we leave the
zone as it is and the domain's ``error`` says how to point it. Otherwise it is
``pending``: publish the two records in its ``records`` (a ``TXT`` at
``_coritan-storage.<hostname>`` and a ``CNAME`` to the bucket's public
host), then call verify. Once verified we request its certificate.

Answers 403 as turning the public URL on does, 409 when the bucket has 10
domains or the hostname is in use on the platform, and 422 for a name
that is not a hostname or belongs to the platform.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID. |
| `bucket_id` | path | integer | yes | The bucket's ID, from `GET /client/object-storage/{service_id}/buckets`. |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `hostname` | string | yes | The hostname, such as `cdn.example.com`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `201` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `201` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `bucket_name` | string |  |
| `public_url` | string or null | The bucket's public URL while it is on. |
| `public_url_enabled` | boolean |  |
| `public_url_available` | boolean | False when the platform offers no public URLs yet. |
| `disabled` | DisabledOut or null | Set when our staff turned public access off. It stays off until they turn it back on. |
| `disabled.at` | string or null |  |
| `disabled.reason` | string or null |  |
| `good_standing` | boolean | Whether the account may turn public access on: a saved payment method, credit or a paid invoice. |
| `website` | WebsiteOut |  |
| `website.enabled` | boolean |  |
| `website.index` | string | The object served for `/` and for every path that ends in `/`. |
| `website.error` | string or null | The object served, with status 404, for a missing key. |
| `website.spa` | boolean | Whether a missing key is answered with the index document and status 200. |
| `domains` | array of DomainOut |  |
| `domains[].hostname` | string |  |
| `domains[].status` | string | `pending` until its records are checked, `verified` once proved, `active` once its certificate is issued, `failed` when the last check did not find the records. |
| `domains[].url` | string or null | `https://<hostname>` once the domain serves the bucket. |
| `domains[].error` | string or null | What the last check found wrong, when `status` is `failed`. For a domain in your own zone, why we could not add its `CNAME` record. |
| `domains[].records` | array of DomainRecord |  |
| `domains[].created_at` | string or null |  |
| `domains[].verified_at` | string or null |  |
| `max_domains` | integer |  |
| `cname_target` | string or null | What each custom domain's CNAME record points at. |
| `rate_limit_per_minute` | integer | Requests one visitor address may make to the public URL in a minute. |

### Unlink a custom domain {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-domains-hostnam}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/domains/{hostname}`

Unlink a custom domain. It stops serving the bucket at once, and a
``CNAME`` record we added to your own zone for it is removed.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID. |
| `bucket_id` | path | integer | yes | The bucket's ID, from `GET /client/object-storage/{service_id}/buckets`. |
| `hostname` | path | string | yes | The custom domain, such as `cdn.example.com`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `bucket_name` | string |  |
| `public_url` | string or null | The bucket's public URL while it is on. |
| `public_url_enabled` | boolean |  |
| `public_url_available` | boolean | False when the platform offers no public URLs yet. |
| `disabled` | DisabledOut or null | Set when our staff turned public access off. It stays off until they turn it back on. |
| `disabled.at` | string or null |  |
| `disabled.reason` | string or null |  |
| `good_standing` | boolean | Whether the account may turn public access on: a saved payment method, credit or a paid invoice. |
| `website` | WebsiteOut |  |
| `website.enabled` | boolean |  |
| `website.index` | string | The object served for `/` and for every path that ends in `/`. |
| `website.error` | string or null | The object served, with status 404, for a missing key. |
| `website.spa` | boolean | Whether a missing key is answered with the index document and status 200. |
| `domains` | array of DomainOut |  |
| `domains[].hostname` | string |  |
| `domains[].status` | string | `pending` until its records are checked, `verified` once proved, `active` once its certificate is issued, `failed` when the last check did not find the records. |
| `domains[].url` | string or null | `https://<hostname>` once the domain serves the bucket. |
| `domains[].error` | string or null | What the last check found wrong, when `status` is `failed`. For a domain in your own zone, why we could not add its `CNAME` record. |
| `domains[].records` | array of DomainRecord |  |
| `domains[].created_at` | string or null |  |
| `domains[].verified_at` | string or null |  |
| `max_domains` | integer |  |
| `cname_target` | string or null | What each custom domain's CNAME record points at. |
| `rate_limit_per_minute` | integer | Requests one visitor address may make to the public URL in a minute. |

### Check a pending domain's DNS records now {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-domains-hostname}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/domains/{hostname}/verify`

Check a pending domain's DNS records now.

The ``TXT`` record must hold the domain's token, and the hostname must
point at the bucket's public host: by ``CNAME``, or by address records
that match it. When both are there the domain is verified and its
certificate is requested. When not, its ``status`` becomes ``failed``
with an ``error`` that says what is missing; publish the records and
check again. A domain already verified is answered as it is.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID. |
| `bucket_id` | path | integer | yes | The bucket's ID, from `GET /client/object-storage/{service_id}/buckets`. |
| `hostname` | path | string | yes | The custom domain, such as `cdn.example.com`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `bucket_name` | string |  |
| `public_url` | string or null | The bucket's public URL while it is on. |
| `public_url_enabled` | boolean |  |
| `public_url_available` | boolean | False when the platform offers no public URLs yet. |
| `disabled` | DisabledOut or null | Set when our staff turned public access off. It stays off until they turn it back on. |
| `disabled.at` | string or null |  |
| `disabled.reason` | string or null |  |
| `good_standing` | boolean | Whether the account may turn public access on: a saved payment method, credit or a paid invoice. |
| `website` | WebsiteOut |  |
| `website.enabled` | boolean |  |
| `website.index` | string | The object served for `/` and for every path that ends in `/`. |
| `website.error` | string or null | The object served, with status 404, for a missing key. |
| `website.spa` | boolean | Whether a missing key is answered with the index document and status 200. |
| `domains` | array of DomainOut |  |
| `domains[].hostname` | string |  |
| `domains[].status` | string | `pending` until its records are checked, `verified` once proved, `active` once its certificate is issued, `failed` when the last check did not find the records. |
| `domains[].url` | string or null | `https://<hostname>` once the domain serves the bucket. |
| `domains[].error` | string or null | What the last check found wrong, when `status` is `failed`. For a domain in your own zone, why we could not add its `CNAME` record. |
| `domains[].records` | array of DomainRecord |  |
| `domains[].created_at` | string or null |  |
| `domains[].verified_at` | string or null |  |
| `max_domains` | integer |  |
| `cname_target` | string or null | What each custom domain's CNAME record points at. |
| `rate_limit_per_minute` | integer | Requests one visitor address may make to the public URL in a minute. |

### Get bucket encryption {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-encryption}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/encryption`

The bucket's default encryption: whether objects written to it are
encrypted, and whether you can turn it on now.

Encryption applies to objects written after it was turned on. Objects
already in the bucket are not encrypted and are not changed.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer | The bucket's ID |
| `enabled` | boolean | True when objects written to the bucket are encrypted |
| `algorithm` | string or null | AES256 while encryption is on, otherwise null |
| `available` | boolean | Whether you can turn encryption on for this bucket now. False when encryption is not offered yet or the service is not active. You can always turn it off while the service is active. |
| `reason` | string or null | Why available is false, in a sentence. Null when it is true. |

### Turn default encryption on or off for the bucket {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-encryption}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/encryption`

Turn default encryption on or off for the bucket.

On encrypts every object written to the bucket from now on with AES-256.
Reading, listing, copying, presigned URLs and the public URL work as
before, and your access keys need nothing extra. Objects already in the
bucket stay as they were. To encrypt them, copy each one over itself or
upload it again. Off stops encrypting new objects and leaves the ones
already encrypted readable. Answers 409 when you turn it on while it is
not offered yet, and 409 when the service is not active. Answers 429 after
60 changes in an hour. The change applies within seconds.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `enabled` | boolean | yes | True encrypts every object written to the bucket from now on. False stops encrypting new objects. Objects already in the bucket keep the state they were written in. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer | The bucket's ID |
| `enabled` | boolean | True when objects written to the bucket are encrypted |
| `algorithm` | string or null | AES256 while encryption is on, otherwise null |
| `available` | boolean | Whether you can turn encryption on for this bucket now. False when encryption is not offered yet or the service is not active. You can always turn it off while the service is active. |
| `reason` | string or null | Why available is false, in a sentence. Null when it is true. |

### The bucket's lifecycle rules: what we delete from it, and when {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle`

The bucket's lifecycle rules: what we delete from it, and when.

New buckets start with one rule (``default_rule_id``) that aborts
unfinished multipart uploads after 7 days. Rules run once a day, so an
object can stay up to a day after its rule makes it due.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `rules` | array of LifecycleRule |  |
| `rules[].id` | string or null | A name for the rule, unique in the bucket. Blank names become rule-1, rule-2 and so on. |
| `rules[].enabled` | boolean | False keeps the rule without applying it |
| `rules[].prefix` | string | Only keys that start with this. Empty means every key. |
| `rules[].tags` | array of LifecycleTag | Only objects with all of these tags, up to 10 |
| `rules[].object_size_greater_than` | integer or null | Only objects larger than this many bytes |
| `rules[].object_size_less_than` | integer or null | Only objects smaller than this many bytes |
| `rules[].expiration_days` | integer or null | Delete objects this many days after they were uploaded |
| `rules[].expiration_date` | string or null | Delete objects from this date on, YYYY-MM-DD, at midnight UTC |
| `rules[].expired_object_delete_marker` | boolean | Remove a delete marker once it is the only version of its key left |
| `rules[].noncurrent_days` | integer or null | Delete an old version this many days after a newer one replaced it |
| `rules[].newer_noncurrent_versions` | integer or null | Keep this many of the newest old versions whatever their age, 1–100. Needs noncurrent_days. |
| `rules[].abort_incomplete_multipart_days` | integer or null | Abort a multipart upload this many days after it started, if it is still unfinished |
| `max_rules` | integer |  |
| `default_rule_id` | string | The ID of the rule new buckets start with |

### Replace the bucket's lifecycle rules with the ones sent, at most 100 {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle`

Replace the bucket's lifecycle rules with the ones sent, at most 100.

Each rule picks objects by key prefix, tags and size, and needs at least
one action: delete objects some days after upload or from a date, delete
old versions some days after they were replaced (keeping the newest few
if asked), remove delete markers that are the only version left, or abort
multipart uploads still unfinished after some days. Days count from the
object's upload time, in UTC. Transitions to another storage class are
refused. Answers 422 with the rule at fault, 409 when the service is not
active, and 429 after 60 rule changes in an hour. An empty list removes
every rule, as DELETE does. Deletions the rules make are free.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `rules` | array of LifecycleRuleIn | yes | Every rule the bucket should have, at most 100. An empty list removes them all. |
| `rules[].id` | string or null | no | A name for the rule, unique in the bucket. Blank names become rule-1, rule-2 and so on. |
| `rules[].enabled` | boolean | no | False keeps the rule without applying it |
| `rules[].prefix` | string | no | Only keys that start with this. Empty means every key. |
| `rules[].tags` | array of LifecycleTag | no | Only objects with all of these tags, up to 10 |
| `rules[].object_size_greater_than` | integer or null | no | Only objects larger than this many bytes |
| `rules[].object_size_less_than` | integer or null | no | Only objects smaller than this many bytes |
| `rules[].expiration_days` | integer or null | no | Delete objects this many days after they were uploaded |
| `rules[].expiration_date` | string or null | no | Delete objects from this date on, YYYY-MM-DD, at midnight UTC |
| `rules[].expired_object_delete_marker` | boolean | no | Remove a delete marker once it is the only version of its key left |
| `rules[].noncurrent_days` | integer or null | no | Delete an old version this many days after a newer one replaced it |
| `rules[].newer_noncurrent_versions` | integer or null | no | Keep this many of the newest old versions whatever their age, 1–100. Needs noncurrent_days. |
| `rules[].abort_incomplete_multipart_days` | integer or null | no | Abort a multipart upload this many days after it started, if it is still unfinished |
| `rules[].transitions` | array of any or null | no | Not offered. Any value is refused, since there is one storage class. |
| `rules[].noncurrent_version_transitions` | array of any or null | no | Not offered, as transitions |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `rules` | array of LifecycleRule |  |
| `rules[].id` | string or null | A name for the rule, unique in the bucket. Blank names become rule-1, rule-2 and so on. |
| `rules[].enabled` | boolean | False keeps the rule without applying it |
| `rules[].prefix` | string | Only keys that start with this. Empty means every key. |
| `rules[].tags` | array of LifecycleTag | Only objects with all of these tags, up to 10 |
| `rules[].object_size_greater_than` | integer or null | Only objects larger than this many bytes |
| `rules[].object_size_less_than` | integer or null | Only objects smaller than this many bytes |
| `rules[].expiration_days` | integer or null | Delete objects this many days after they were uploaded |
| `rules[].expiration_date` | string or null | Delete objects from this date on, YYYY-MM-DD, at midnight UTC |
| `rules[].expired_object_delete_marker` | boolean | Remove a delete marker once it is the only version of its key left |
| `rules[].noncurrent_days` | integer or null | Delete an old version this many days after a newer one replaced it |
| `rules[].newer_noncurrent_versions` | integer or null | Keep this many of the newest old versions whatever their age, 1–100. Needs noncurrent_days. |
| `rules[].abort_incomplete_multipart_days` | integer or null | Abort a multipart upload this many days after it started, if it is still unfinished |
| `max_rules` | integer |  |
| `default_rule_id` | string | The ID of the rule new buckets start with |

### Remove every lifecycle rule from the bucket, the default one included {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle`

Remove every lifecycle rule from the bucket, the default one included.
Nothing is deleted from it on a schedule after this.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `rules` | array of LifecycleRule |  |
| `rules[].id` | string or null | A name for the rule, unique in the bucket. Blank names become rule-1, rule-2 and so on. |
| `rules[].enabled` | boolean | False keeps the rule without applying it |
| `rules[].prefix` | string | Only keys that start with this. Empty means every key. |
| `rules[].tags` | array of LifecycleTag | Only objects with all of these tags, up to 10 |
| `rules[].object_size_greater_than` | integer or null | Only objects larger than this many bytes |
| `rules[].object_size_less_than` | integer or null | Only objects smaller than this many bytes |
| `rules[].expiration_days` | integer or null | Delete objects this many days after they were uploaded |
| `rules[].expiration_date` | string or null | Delete objects from this date on, YYYY-MM-DD, at midnight UTC |
| `rules[].expired_object_delete_marker` | boolean | Remove a delete marker once it is the only version of its key left |
| `rules[].noncurrent_days` | integer or null | Delete an old version this many days after a newer one replaced it |
| `rules[].newer_noncurrent_versions` | integer or null | Keep this many of the newest old versions whatever their age, 1–100. Needs noncurrent_days. |
| `rules[].abort_incomplete_multipart_days` | integer or null | Abort a multipart upload this many days after it started, if it is still unfinished |
| `max_rules` | integer |  |
| `default_rule_id` | string | The ID of the rule new buckets start with |

### List lifecycle runs {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-lifecycle-runs}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/lifecycle/runs`

The latest daily runs of the bucket's lifecycle rules, newest first:
when each ran, what it removed and aborted, and what went wrong.

A run that stops before the end of a large bucket says so with
``complete`` false, and the next run carries on where it stopped. What a
run could not delete is still due, and the next run tries again.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID |
| `bucket_id` | path | integer | yes | The bucket's ID, from the service's bucket list |
| `limit` | query | integer | no | How many runs to return, newest first, 1–100 Default: `20`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `items` | array of LifecycleRun |  |
| `items[].id` | integer |  |
| `items[].started_at` | string or null |  |
| `items[].finished_at` | string or null | Empty while the run is going |
| `items[].removed_objects` | integer | Objects, old versions and delete markers removed |
| `items[].removed_bytes` | integer | Bytes deleted for good |
| `items[].aborted_uploads` | integer |  |
| `items[].complete` | boolean | False when the run stopped before the end of the bucket. The next run carries on from there. |
| `items[].error` | string or null |  |
| `total` | integer |  |

### The bucket's event notification rules, oldest first {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications`

The bucket's event notification rules, oldest first.

Each rule names its `events`, the `prefix` and `suffix` a key must have,
the `url` events go to, its `status` (`active` or `paused`, with
`paused_reason` when we paused it after a day of failed deliveries), when
a delivery last worked or failed, and how many are waiting (`pending`).
The signing secret is never listed. `limits` holds the rules a bucket may
have and the retry schedule; `events` lists what each event covers.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, as `GET .../buckets` lists it |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Add a rule: POST each matching event in the bucket to url {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications`

Add a rule: POST each matching event in the bucket to `url`.

Answers the rule and its `signing_secret`, which is shown this once; keep
it to check the `X-Coritan-Signature` header of each delivery. Refused
with 422 when the address is not https, is inside Coritan, or resolves
to a private, loopback or link-local network; with 409 when the bucket
already has 100 rules or the rule overlaps another (they share an event
and a key could match both filters).

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, as `GET .../buckets` lists it |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `events` | array of string | yes | What to send: `object-create` (PutObject, CopyObject, CompleteMultipartUpload, PostObject), `object-delete` (DeleteObject, DeleteObjects, LifecycleDeletion), or both |
| `url` | string | yes | The https:// address to POST each event to |
| `prefix` | string | no | Only keys that start with this |
| `suffix` | string | no | Only keys that end with this |
| `description` | string or null | no | Your own words for the rule |

#### Responses

| Status | Meaning |
| --- | --- |
| `201` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Change a rule {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rule}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}`

Change a rule. Fields left out stay as they are.

`enabled: false` pauses it and cancels the events waiting to be sent;
`enabled: true` turns it back on, and it sends changes made from then on.
The same checks as creating a rule apply.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, as `GET .../buckets` lists it |
| `rule_id` | path | integer | yes | The notification rule's id |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `events` | array of string or null | no | As when creating; leave it out to keep it |
| `url` | string or null | no | A new https:// address |
| `prefix` | string or null | no | A new prefix; "" for none |
| `suffix` | string or null | no | A new suffix; "" for none |
| `description` | string or null | no | New words |
| `enabled` | boolean or null | no | false pauses the rule and cancels its queued events; true turns it back on |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Delete a rule {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-r}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}`

Delete a rule. Events waiting to be sent for it are cancelled.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, as `GET .../buckets` lists it |
| `rule_id` | path | integer | yes | The notification rule's id |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### The rule's deliveries of the last 30 days, newest first {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rule}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}/deliveries`

The rule's deliveries of the last 30 days, newest first.

Each names the event (`event_name`, the object `key`, `size`, `etag`,
`version_id`, `event_time`), its `status` (`pending`, `sending`,
`delivered`, `failed`, `cancelled`), the attempts made, when the next is
due, and the address's `response_status` and the start of its
`response_body`. `next_before_id` is null on the last page.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, as `GET .../buckets` lists it |
| `rule_id` | path | integer | yes | The notification rule's id |
| `status` | query | string or null | no | Only deliveries in this state: pending, sending, delivered, failed, cancelled |
| `limit` | query | integer | no | Deliveries per page, newest first Default: `50`. |
| `before_id` | query | integer or null | no | The `next_before_id` of the previous page, for the page after it |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Replace the rule's signing secret and answer the new one, shown this once {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rul}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}/rotate-secret`

Replace the rule's signing secret and answer the new one, shown this
once. Every delivery from now on is signed with it, retries of earlier
events included, so update your receiver straight away.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, as `GET .../buckets` lists it |
| `rule_id` | path | integer | yes | The notification rule's id |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Send test notification {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-notifications-rul}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/notifications/{rule_id}/test`

Send the rule's address a test event now, signed like any other, and
answer what it replied.

The body is `{"Service": "Coritan Object Storage", "Event":
"s3:TestEvent", ...}`. `delivered` is true when the address answered
with a 2xx status; `response_status` and `response_body` hold what it
said. A test is never retried and never pauses the rule. It works on a
paused rule too, so you can check a fix before turning it back on.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, as `GET .../buckets` lists it |
| `rule_id` | path | integer | yes | The notification rule's id |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Get bucket object lock {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-object-lock}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/object-lock`

Whether the bucket has Object Lock, and the default retention it gives
every new version: ``mode`` (``GOVERNANCE`` or ``COMPLIANCE``) and
``days``, or null for none. ``years`` repeats ``days`` when it is a whole
number of years.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `enabled` | boolean | Whether the bucket was created with Object Lock |
| `mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | The default retention's mode; null for no default retention |
| `days` | integer or null | How long the default retention keeps each new version, in days |
| `years` | integer or null | ``days`` in years, when it is a whole number of years |
| `bucket_id` | integer |  |

### Change the default retention of a bucket with Object Lock {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-object-lock}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/object-lock`

Change the default retention of a bucket with Object Lock.

Send a ``mode`` with ``days`` or ``years``, or ``mode`` null to remove
the default. Versions that already exist keep the retention they have.
A compliance default can only be made longer and stays compliance:
anything else answers 409 with the current ``mode`` and ``days``. To
shorten or remove a governance default, set ``confirm`` to the bucket's
name, or the answer is 422. A bucket created without Object Lock
answers 409, because Object Lock can only be chosen at creation.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | no | The default retention's mode; null removes the default retention |
| `days` | integer or null | no | How long, in days, from 1 to 36500 |
| `years` | integer or null | no | How long, in years, from 1 to 100, instead of days |
| `confirm` | string or null | no | The bucket's name, needed to shorten or remove a governance default |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `enabled` | boolean | Whether the bucket was created with Object Lock |
| `mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | The default retention's mode; null for no default retention |
| `days` | integer or null | How long the default retention keeps each new version, in days |
| `years` | integer or null | ``days`` in years, when it is a whole number of years |
| `bucket_id` | integer |  |

### One page of the bucket under prefix, folders first {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-objects}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects`

One page of the bucket under ``prefix``, folders first.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes |  |
| `bucket_id` | path | integer | yes |  |
| `prefix` | query | string | no |  |
| `token` | query | string or null | no |  |
| `max_keys` | query | integer | no | Default: `200`. |
| `flat` | query | boolean | no | No folder collapsing: every key under the prefix Default: `False`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type |
| --- | --- |
| `items` | array of ObjectItem |
| `items[].key` | string |
| `items[].size` | integer or null |
| `items[].last_modified` | string or null |
| `items[].etag` | string or null |
| `items[].is_prefix` | boolean |
| `prefix` | string |
| `next_token` | string or null |

### Delete named objects {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-objects}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects`

Delete named objects. Per-key failures are reported, not raised.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `service_id` | path | integer | yes |
| `bucket_id` | path | integer | yes |

#### Request body

`application/json` (required)

| Field | Type | Required |
| --- | --- | --- |
| `keys` | array of string | yes |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type |
| --- | --- |
| `deleted` | integer |
| `errors` | array of object |

### Get object details {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-details}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/details`

One version of an object: its size, type, metadata and tags, its
retention and legal hold, and the key's versions. Answers 404 for a key
or version that does not exist, or a version that is a delete marker.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |
| `key` | query | string | yes | The object's key |
| `version_id` | query | string or null | no | A version's id; the current version when left out |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `key` | string |  |
| `version_id` | string |  |
| `is_latest` | boolean |  |
| `size` | integer |  |
| `content_type` | string or null |  |
| `etag` | string or null |  |
| `last_modified` | string or null |  |
| `metadata` | Metadata | The object's ``x-amz-meta-*`` values |
| `tags` | array of TagOut |  |
| `tags[].key` | string |  |
| `tags[].value` | string |  |
| `retention` | RetentionView or null |  |
| `retention.mode` | string, one of `GOVERNANCE`, `COMPLIANCE` |  |
| `retention.until` | string | When the retention ends, UTC |
| `retention.active` | boolean | False once the date has passed |
| `legal_hold` | boolean |  |
| `object_lock` | boolean | Whether the bucket has Object Lock, so retention and legal holds apply |
| `versioning` | string, one of `off`, `enabled`, `suspended` |  |
| `versions` | array of VersionItem | This key's versions and delete markers, newest first, up to 50 |
| `versions[].key` | string |  |
| `versions[].version_id` | string | The version's id; ``null`` for an object written while versioning was off |
| `versions[].is_latest` | boolean | Whether this is the object's current version |
| `versions[].is_delete_marker` | boolean | A delete marker hides the object; deleting the marker brings it back |
| `versions[].size` | integer or null |  |
| `versions[].last_modified` | string or null |  |
| `versions[].etag` | string or null |  |
| `versions_truncated` | boolean | True when the key has more than 50 |

### Put a legal hold on a version, or take it off {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-legal-hold}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/legal-hold`

Put a legal hold on a version, or take it off. While a version has a
legal hold nobody can delete it, whatever its retention says. Answers
409 on a bucket without Object Lock.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | yes | The object's key |
| `version_id` | string or null | no | The version's id; the current version when left out |
| `on` | boolean | yes | True puts a legal hold on the version; false takes it off |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type |
| --- | --- |
| `key` | string |
| `version_id` | string |
| `legal_hold` | boolean |

### A short-lived URL the browser uses directly for one GET, PUT or DELETE {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-presign}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/presign`

A short-lived URL the browser uses directly for one GET, PUT or DELETE.

Anyone who has the URL can use it until it expires. We count each request
made with it like one signed with your own key and bill it to your
account, as the bucket's owner.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `service_id` | path | integer | yes |
| `bucket_id` | path | integer | yes |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | yes |  |
| `op` | string, one of `get`, `put`, `delete` | yes |  |
| `content_type` | string or null | no |  |
| `expires` | integer or null | no |  |
| `download` | boolean | no |  |
| `version_id` | string or null | no | For get: the version to download, from the versions list. Leave out for the current one |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `url` | string |  |
| `method` | string |  |
| `headers` | Headers |  |
| `expires_in` | integer |  |
| `expires_at` | string |  |
| `version_id` | string or null | The version the URL downloads, when one was asked for |

### Restore object version {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-restore}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/restore`

Make an older version current again by copying it over the current
one, with its metadata and tags. The version it replaces is kept. Answers
409 on a bucket that does not keep versions, 404 for a version that does
not exist, and 422 for a version larger than 5 GB.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | yes |  |
| `version_id` | string | yes | The version to copy over the current one |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `ok` | boolean |  |
| `key` | string |  |
| `restored_from` | string |  |
| `version_id` | string | The id of the new current version |

### Give a version a retention, or change the one it has {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-retention}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/retention`

Give a version a retention, or change the one it has.

Compliance retention can only be made longer and stays compliance:
anything else answers 409 with ``locked_until``. Governance retention can
be made longer freely; to shorten it, or to remove it with ``mode``
null, set ``confirm`` to the object's name after the last ``/``, or the
answer is 422. Removed governance retention ends within a minute.
Answers 409 on a bucket without Object Lock, and 422 for a date less
than a minute ahead or more than 100 years ahead.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | yes | The object's key |
| `version_id` | string or null | no | The version's id; the current version when left out |
| `mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | no | The retention's mode; null removes governance retention, which then ends within a minute |
| `until` | string (date-time) or null | no | When the retention ends, ISO 8601; at least a minute ahead |
| `confirm` | string or null | no | The object's name after the last ``/``, needed to shorten or remove governance retention |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `key` | string |  |
| `version_id` | string |  |
| `retention` | RetentionView or null |  |
| `retention.mode` | string, one of `GOVERNANCE`, `COMPLIANCE` |  |
| `retention.until` | string | When the retention ends, UTC |
| `retention.active` | boolean | False once the date has passed |

### Delete one version or delete marker for good {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-version}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/version`

Delete one version or delete marker for good. There is no undo.

A version with a legal hold, or under compliance retention, answers 409;
for compliance ``locked_until`` says when it can be deleted. A version
under governance retention answers 409 unless ``bypass_governance`` is
true and ``confirm`` is the object's name after the last ``/`` (422
when it does not match). Deleting a delete marker makes the version
under it current again.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `key` | string | yes |  |
| `version_id` | string | yes | The version or delete marker to remove |
| `bypass_governance` | boolean | no | Delete a version under governance retention anyway |
| `confirm` | string or null | no | The object's name after the last ``/``, needed with ``bypass_governance`` |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `ok` | boolean |  |
| `key` | string |  |
| `version_id` | string |  |
| `delete_marker` | boolean | True when what was removed was a delete marker |

### List object versions {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-objects-versions}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/objects/versions`

One page of every version and delete marker under ``prefix``, by key
and newest first, with the folders under it. A bucket that never kept
versions lists each object once, with ``version_id`` ``null``.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |
| `prefix` | query | string | no | Only keys that start with this |
| `key_marker` | query | string or null | no | ``next_key_marker`` from the page before |
| `version_marker` | query | string or null | no | ``next_version_marker`` from the page before |
| `max_keys` | query | integer | no | Versions and delete markers per page, from 1 to 1000 Default: `100`. |
| `flat` | query | boolean | no | Every key under the prefix, with no folders Default: `False`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `items` | array of VersionItem |  |
| `items[].key` | string |  |
| `items[].version_id` | string | The version's id; ``null`` for an object written while versioning was off |
| `items[].is_latest` | boolean | Whether this is the object's current version |
| `items[].is_delete_marker` | boolean | A delete marker hides the object; deleting the marker brings it back |
| `items[].size` | integer or null |  |
| `items[].last_modified` | string or null |  |
| `items[].etag` | string or null |  |
| `prefixes` | array of string | Folders directly under ``prefix``; empty when ``flat`` is true |
| `prefix` | string |  |
| `next_key_marker` | string or null | Pass back as ``key_marker`` for the next page |
| `next_version_marker` | string or null | Pass back as ``version_marker`` for the next page |

### Get public access {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-public}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/public`

How the bucket is served to the public: its public URL, its custom
domains with the DNS records each needs, and its website settings.

``public_url_available`` is false when the platform offers no public URLs
yet; custom domains still work then. ``disabled`` is set when our staff
turned public access off. Answers 404 for a bucket that is not this
service's.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID. |
| `bucket_id` | path | integer | yes | The bucket's ID, from `GET /client/object-storage/{service_id}/buckets`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `bucket_name` | string |  |
| `public_url` | string or null | The bucket's public URL while it is on. |
| `public_url_enabled` | boolean |  |
| `public_url_available` | boolean | False when the platform offers no public URLs yet. |
| `disabled` | DisabledOut or null | Set when our staff turned public access off. It stays off until they turn it back on. |
| `disabled.at` | string or null |  |
| `disabled.reason` | string or null |  |
| `good_standing` | boolean | Whether the account may turn public access on: a saved payment method, credit or a paid invoice. |
| `website` | WebsiteOut |  |
| `website.enabled` | boolean |  |
| `website.index` | string | The object served for `/` and for every path that ends in `/`. |
| `website.error` | string or null | The object served, with status 404, for a missing key. |
| `website.spa` | boolean | Whether a missing key is answered with the index document and status 200. |
| `domains` | array of DomainOut |  |
| `domains[].hostname` | string |  |
| `domains[].status` | string | `pending` until its records are checked, `verified` once proved, `active` once its certificate is issued, `failed` when the last check did not find the records. |
| `domains[].url` | string or null | `https://<hostname>` once the domain serves the bucket. |
| `domains[].error` | string or null | What the last check found wrong, when `status` is `failed`. For a domain in your own zone, why we could not add its `CNAME` record. |
| `domains[].records` | array of DomainRecord |  |
| `domains[].created_at` | string or null |  |
| `domains[].verified_at` | string or null |  |
| `max_domains` | integer |  |
| `cname_target` | string or null | What each custom domain's CNAME record points at. |
| `rate_limit_per_minute` | integer | Requests one visitor address may make to the public URL in a minute. |

### Turn the bucket's public URL on or off {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-public}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/public`

Turn the bucket's public URL on or off.

While it is on, anyone with a link can read every object in the bucket at
``https://<token>.<public domain>/<key>``, and each read our edge does not
answer from its cache counts as a Class B operation. Listing the bucket is
never public. The URL keeps its token when you turn it off and on again.

Turning it on answers 403 when the account has no saved payment method,
no credit and no paid invoice, and when our staff turned public access off
for the bucket; 409 when the platform offers no public URLs yet.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID. |
| `bucket_id` | path | integer | yes | The bucket's ID, from `GET /client/object-storage/{service_id}/buckets`. |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `enabled` | boolean | yes | True to serve the bucket at its public URL, false to stop. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `bucket_name` | string |  |
| `public_url` | string or null | The bucket's public URL while it is on. |
| `public_url_enabled` | boolean |  |
| `public_url_available` | boolean | False when the platform offers no public URLs yet. |
| `disabled` | DisabledOut or null | Set when our staff turned public access off. It stays off until they turn it back on. |
| `disabled.at` | string or null |  |
| `disabled.reason` | string or null |  |
| `good_standing` | boolean | Whether the account may turn public access on: a saved payment method, credit or a paid invoice. |
| `website` | WebsiteOut |  |
| `website.enabled` | boolean |  |
| `website.index` | string | The object served for `/` and for every path that ends in `/`. |
| `website.error` | string or null | The object served, with status 404, for a missing key. |
| `website.spa` | boolean | Whether a missing key is answered with the index document and status 200. |
| `domains` | array of DomainOut |  |
| `domains[].hostname` | string |  |
| `domains[].status` | string | `pending` until its records are checked, `verified` once proved, `active` once its certificate is issued, `failed` when the last check did not find the records. |
| `domains[].url` | string or null | `https://<hostname>` once the domain serves the bucket. |
| `domains[].error` | string or null | What the last check found wrong, when `status` is `failed`. For a domain in your own zone, why we could not add its `CNAME` record. |
| `domains[].records` | array of DomainRecord |  |
| `domains[].created_at` | string or null |  |
| `domains[].verified_at` | string or null |  |
| `max_domains` | integer |  |
| `cname_target` | string or null | What each custom domain's CNAME record points at. |
| `rate_limit_per_minute` | integer | Requests one visitor address may make to the public URL in a minute. |

### Purge cache {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-public-purge}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/public/purge`

Make our edge forget what it cached for the bucket, on its public URL
and every custom domain. Name up to 100 ``paths`` to purge those alone, or
leave them out to purge everything. The next request for each path reads
the object again. Answers 409 when nothing serves the bucket.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID. |
| `bucket_id` | path | integer | yes | The bucket's ID, from `GET /client/object-storage/{service_id}/buckets`. |

#### Request body

`application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `paths` | array of string or null | no | Paths to purge, such as `/images/logo.png`. Leave it out to purge everything the bucket serves. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `hosts` | array of string | The hostnames whose cached copies were purged. |
| `paths` | array of string | The paths purged; empty when everything was. |

### The bucket's replication rules, the buckets a new rule may copy to, and the limits {#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-replication}

`GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication`

The bucket's replication rules, the buckets a new rule may copy to,
and the limits.

Each rule has its destination (``dest_bucket_id``, ``dest_bucket_name``,
``dest_region``), ``prefix``, ``replicate_deletes``, ``enabled`` and its
``status``: ``copying`` while the objects the bucket held when the rule
was made are copied, ``active``, ``paused``, or ``error`` when the last
pass could not copy everything (``last_failures``, ``last_error``).
``replicated_through`` is the time up to which every change has reached
the destination, and ``lag_seconds`` how long ago that was; both are
null until the first copy ends. ``objects_copied``, ``bytes_copied`` and
``objects_deleted`` count since the rule was made.

``destinations`` lists your buckets in other regions. Answers 404 for a
service or bucket that is not this account's.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The source bucket's id |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Add replication rule {#op-post-api-v1-client-object-storage-service-id-buckets-bucket-id-replication}

`POST /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication`

Copy this bucket's objects into another of your buckets in another
region, and keep copying. The first copy of what the bucket holds starts
within five minutes; after it, new and changed objects are copied every
five minutes, and once a day we check that the destination holds
everything. With ``replicate_deletes``, that daily check also removes
from the destination what the source no longer holds under the prefix.
Keys stay the same. Copies are free; the storage they take is billed as
storage in the destination's service.

Answers the rule as ``GET`` lists it. Answers 404 for a service or
bucket that is not this account's, 409 when the service is not active,
when the bucket already has 10 rules or this one, when the destination
copies into this bucket already (replication cannot run in a circle),
or when another rule copies into the same keys of a destination that
replicates deletes; 422 when the destination is in the same region; and
429 after 60 rule changes in an hour.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The source bucket's id |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `dest_bucket_id` | integer | yes | The bucket to copy into: one of your buckets in another region, from destinations |
| `prefix` | string | no | Copy only the keys that start with this. Empty copies the whole bucket |
| `replicate_deletes` | boolean | no | When true, the daily check also deletes from the destination the objects under the prefix that the source no longer holds |

#### Responses

| Status | Meaning |
| --- | --- |
| `201` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Change a rule's prefix, turn replicated deletes on or off, or pause and resume it {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-replication-rule-i}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication/{rule_id}`

Change a rule's prefix, turn replicated deletes on or off, or pause
and resume it. Only the fields sent change. A new prefix runs the first
copy again; a paused rule picks up the changes it missed when it starts
again.

Answers the rule. Answers 404 for a rule that is not this account's,
409 when the service is not active or the change conflicts with
another rule, and 429 after 60 rule changes in an hour.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The source bucket's id |
| `rule_id` | path | integer | yes | The rule's id, from the list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `prefix` | string or null | no | A new prefix. The first copy runs again for it |
| `replicate_deletes` | boolean or null | no | Turn replicated deletes on or off |
| `enabled` | boolean or null | no | False pauses the rule; true starts it again from where it stopped |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Remove a rule {#op-delete-api-v1-client-object-storage-service-id-buckets-bucket-id-replication-rul}

`DELETE /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/replication/{rule_id}`

Remove a rule. Nothing more is copied; the objects it already copied
stay in the destination. Works whatever the service's status.

Answers ``{"deleted": true, "id"}``. Answers 404 for a rule that is not
this account's and 429 after 60 rule changes in an hour.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The source bucket's id |
| `rule_id` | path | integer | yes | The rule's id, from the list |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Turn versioning on for a bucket, or suspend it {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-versioning}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/versioning`

Turn versioning on for a bucket, or suspend it.

While versioning is on, every overwrite and delete keeps the version it
replaces, and those versions count toward the GB-months you are billed
for. Suspending stops keeping new versions and keeps the ones the bucket
holds. Versioning cannot be turned off once it is on, so ``off`` is not
accepted. Answers 409 for ``suspended`` on a bucket with Object Lock,
which keeps versioning on, and when the service is not active.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's id |
| `bucket_id` | path | integer | yes | The bucket's id, from the bucket list |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string, one of `enabled`, `suspended` | yes | ``enabled`` keeps every version of every object; ``suspended`` stops keeping new ones and keeps the versions the bucket holds. Versioning cannot be turned off once it is on |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `versioning` | string, one of `off`, `enabled`, `suspended` |  |
| `object_lock` | ObjectLockOut | A bucket's Object Lock and the default retention it gives new versions. |
| `object_lock.enabled` | boolean | Whether the bucket was created with Object Lock |
| `object_lock.mode` | string, one of `GOVERNANCE`, `COMPLIANCE` or null | The default retention's mode; null for no default retention |
| `object_lock.days` | integer or null | How long the default retention keeps each new version, in days |
| `object_lock.years` | integer or null | ``days`` in years, when it is a whole number of years |

### Serve the bucket as a static website on its public URL and custom domains {#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-website}

`PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/website`

Serve the bucket as a static website on its public URL and custom domains.

With ``enabled``, ``/`` and every path ending in ``/`` answer with the
``index`` document under that prefix (default ``index.html``), and a path
with no object whose ``<path>/<index>`` exists redirects to ``<path>/``.
A missing key answers with the ``error`` document and status 404, or,
with ``spa``, with the root index document and status 200, which is what
a single page app needs. ``error`` and ``spa`` cannot both be set (422).
Saving purges what the edge cached for the bucket.

Authentication: an access token, sent as `Authorization: Bearer <token>`.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `service_id` | path | integer | yes | The Object Storage service's ID. |
| `bucket_id` | path | integer | yes | The bucket's ID, from `GET /client/object-storage/{service_id}/buckets`. |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `enabled` | boolean | yes | True to answer `/` and paths ending in `/` with the index document. |
| `index` | string or null | no | The index document's key. Default `index.html`. |
| `error` | string or null | no | The error document's key, served with status 404. |
| `spa` | boolean | no | Answer every missing key with the index document and status 200. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

Fields of a `200` response:

| Field | Type | Description |
| --- | --- | --- |
| `bucket_id` | integer |  |
| `bucket_name` | string |  |
| `public_url` | string or null | The bucket's public URL while it is on. |
| `public_url_enabled` | boolean |  |
| `public_url_available` | boolean | False when the platform offers no public URLs yet. |
| `disabled` | DisabledOut or null | Set when our staff turned public access off. It stays off until they turn it back on. |
| `disabled.at` | string or null |  |
| `disabled.reason` | string or null |  |
| `good_standing` | boolean | Whether the account may turn public access on: a saved payment method, credit or a paid invoice. |
| `website` | WebsiteOut |  |
| `website.enabled` | boolean |  |
| `website.index` | string | The object served for `/` and for every path that ends in `/`. |
| `website.error` | string or null | The object served, with status 404, for a missing key. |
| `website.spa` | boolean | Whether a missing key is answered with the index document and status 200. |
| `domains` | array of DomainOut |  |
| `domains[].hostname` | string |  |
| `domains[].status` | string | `pending` until its records are checked, `verified` once proved, `active` once its certificate is issued, `failed` when the last check did not find the records. |
| `domains[].url` | string or null | `https://<hostname>` once the domain serves the bucket. |
| `domains[].error` | string or null | What the last check found wrong, when `status` is `failed`. For a domain in your own zone, why we could not add its `CNAME` record. |
| `domains[].records` | array of DomainRecord |  |
| `domains[].created_at` | string or null |  |
| `domains[].verified_at` | string or null |  |
| `max_domains` | integer |  |
| `cname_target` | string or null | What each custom domain's CNAME record points at. |
| `rate_limit_per_minute` | integer | Requests one visitor address may make to the public URL in a minute. |
