Cosmoner Docs
API Reference

Storage

Manage object storage buckets, IAM users, container registries, and repositories.

Object Storage

List Buckets

GET /v1/projects/:projectId/storage/object-storage

Returns buckets with S3 endpoint info, including CDN status (cdnEnabled, cdnDomain).

Auth: Required (member, scope: storage:read)

Preview Cost

GET /v1/projects/:projectId/storage/object-storage/preview?provider=<provider>&tier=<tier>

Returns a prorated cost preview for a bucket tier, including the subtotal, estimated tax, any applied credit, and the total due today. The tier parameter defaults to STARTER.

Available tiers: STARTER ($5/mo), GROWTH ($20/mo), SCALE ($75/mo), ENTERPRISE ($300/mo).

Auth: Required (member)

Create Bucket

POST /v1/projects/:projectId/storage/object-storage

Provisions an S3-compatible bucket on a prepaid tier. The prorated amount is charged to the project's payment method off-session and the response is { deployed: true }. If the project has no card, the request returns 402 — see Billing → Deploy Payment Errors.

Request Body:

{
  "name": "my-bucket",
  "provider": "AWS_S3",
  "region": "eu-north-1",
  "tier": "STARTER",
  "publicAccess": false,
  "versioning": false,
  "cdnEnabled": false,
  "corsRules": [
    {
      "allowedOrigins": ["https://example.com"],
      "allowedMethods": ["GET", "PUT"],
      "allowedHeaders": ["*"],
      "exposeHeaders": ["ETag"],
      "maxAgeSeconds": 3600
    }
  ]
}

Each tier includes storage, egress, and request allowances. Usage is monitored and the bucket is suspended when the tier limit is exceeded by 10% (grace buffer). Upgrade to a higher tier to resume.

corsRules is optional. Each rule requires at least one allowedOrigins entry (use "*" to allow any origin) and one allowedMethods entry (GET, PUT, POST, DELETE, HEAD). allowedHeaders, exposeHeaders, and maxAgeSeconds are optional.

cdnEnabled is optional (defaults to false) and serves the bucket's public objects through a global CDN for faster delivery worldwide. It requires publicAccess: true; CloudFront delivery is metered at $0.12/GB and $0.015 per 10K requests. It can also be toggled after creation — see Update CDN below.

Auth: Required (member, write access, scope: storage:write)

Get Usage

GET /v1/projects/:projectId/storage/object-storage/:bucketId/usage

Returns current storage, egress, and request usage for a bucket, along with the tier allowances. Usage is fetched from CloudWatch metrics (may have up to 24h delay).

Auth: Required (member, scope: storage:read)

Change Tier

PATCH /v1/projects/:projectId/storage/object-storage/:bucketId/tier

Changes a bucket to a different tier. If the bucket was suspended due to exceeding its tier, upgrading reactivates it. Downgrades are allowed only when current usage fits within the target tier's limits.

Request Body:

{
  "tier": "GROWTH"
}

Auth: Required (member, write access, scope: storage:write)

Update CORS

PATCH /v1/projects/:projectId/storage/object-storage/:bucketId/cors

Replaces the bucket's CORS (Cross-Origin Resource Sharing) configuration. The full rule set is applied at once — send the complete list, not a delta. An empty corsRules array clears the configuration.

Request Body:

{
  "corsRules": [
    {
      "allowedOrigins": ["https://example.com", "https://app.example.com"],
      "allowedMethods": ["GET", "PUT", "POST"],
      "allowedHeaders": ["*"],
      "exposeHeaders": ["ETag"],
      "maxAgeSeconds": 3600
    }
  ]
}

Auth: Required (member, write access, scope: storage:write)

Update CDN

PATCH /v1/projects/:projectId/storage/object-storage/:bucketId/cdn

Enables or disables the CDN add-on for a bucket. Enabling requires the bucket to already have publicAccess set to true — otherwise the request returns 400. Delivery is metered at $0.12/GB and $0.015 per 10K requests while the CDN is enabled.

Request Body:

{
  "cdnEnabled": true
}

Response Data:

{
  "cdnEnabled": true,
  "cdnDomain": "d1234abcd.cloudfront.net"
}

cdnDomain is null while disabled or before the CDN has finished provisioning.

Auth: Required (member, write access, scope: storage:write)

Delete Bucket

DELETE /v1/projects/:projectId/storage/object-storage/:bucketId

Deletes the S3 bucket and removes the Stripe subscription item.

Auth: Required (member, write access, scope: storage:write)

List IAM Users

GET /v1/projects/:projectId/storage/object-storage/:bucketId/iam-users

Auth: Required (member)

Create IAM User

POST /v1/projects/:projectId/storage/object-storage/:bucketId/iam-users

Creates an IAM user with an access key and secret. Credentials are returned once and cannot be retrieved again.

Auth: Required (member, write access, scope: storage:write)

Delete IAM User

DELETE /v1/projects/:projectId/storage/object-storage/:bucketId/iam-users/:iamUserName

Auth: Required (member, write access, scope: storage:write)


Container Registry

List Registries

GET /v1/projects/:projectId/storage/container-registry

Returns registries with their repositories.

Auth: Required (member, scope: storage:read)

Get Registry

GET /v1/projects/:projectId/storage/container-registry/:id

Auth: Required (member)

List Available Regions

GET /v1/projects/:projectId/storage/container-registry/regions

Returns the regions a Cosmoner registry can be created in, as { "value": "eu-north-1", "label": "Europe (Stockholm)" } objects.

Auth: Required (member)

Preview Cost

GET /v1/projects/:projectId/storage/container-registry/preview

Returns a prorated cost preview for the registry's $1/month fee, including the subtotal, estimated tax, any applied credit, and the total due today. Storage and egress are metered after the fact and are not part of the preview — see Container Registry for those rates.

Auth: Required (member)

Create Registry

POST /v1/projects/:projectId/storage/container-registry

Creates a managed Cosmoner registry: the subscription items for its $1/month fee, metered storage, and metered egress, plus the settings every repository added under it inherits. region must be one of the values returned by the regions endpoint and is fixed for the life of the registry.

The prorated fee is charged to the project's payment method off-session and the response is { deployed: true, id }. If the project has no card, the request returns 402 — see Billing → Deploy Payment Errors.

{
  "name": "my-registry",
  "region": "eu-north-1",
  "imageTagMutability": "MUTABLE",
  "scanOnPush": true,
  "encryptionType": "AES256",
  "lifecycleEnabled": true,
  "lifecycleKeepLastN": 10,
  "lifecycleUntaggedAfterDays": 7
}
FieldDefaultNotes
imageTagMutabilityMUTABLEIMMUTABLE rejects a second push to an existing tag.
scanOnPushtrueScans each pushed image for known vulnerabilities.
encryptionTypeAES256KMS requires kmsKeyArn and cannot be changed for existing repositories.
kmsKeyArnRequired when encryptionType is KMS.
lifecycleEnabledtrueExpires old images automatically.
lifecycleKeepLastN101–1000. Images beyond this count expire.
lifecycleUntaggedAfterDays71–365. Untagged images expire after this many days.

Auth: Required (member, write access, scope: storage:write)

Update Registry

PATCH /v1/projects/:projectId/storage/container-registry/:id

Updates a registry's settings. At least one field must be provided. Tag mutability and scanning are re-applied to every existing repository; encryption applies only to repositories created afterwards, because it is fixed when a repository is created.

Auth: Required (member, write access, scope: storage:write)

Delete Registry

DELETE /v1/projects/:projectId/storage/container-registry/:id

Deletes every repository under the registry and stops its fee, storage, and egress charges. Billing is stopped before anything is deleted: if that fails the registry is kept and the request returns 502, so the deletion can be retried without losing track of what is still being charged.

Auth: Required (member, write access, scope: storage:write)

List Repositories

GET /v1/projects/:projectId/storage/container-registry/:id/repositories

Auth: Required (member)

Create Repository

POST /v1/projects/:projectId/storage/container-registry/:id/repositories

Auth: Required (member, write access, scope: storage:write)

Request Body:

{
  "name": "my-app",
  "visibility": "PRIVATE",
  "publicEgressCapGb": null
}

Names must be lowercase and may contain dots, hyphens, and underscores.

FieldDefaultNotes
visibilityPRIVATEPUBLIC allows anonymous pulls. Pushes always require an API key.
publicEgressCapGbRequired when visibility is PUBLIC. 1–10,000 GB of anonymous egress per billing period; the repository reverts to PRIVATE when it is reached.

Update Repository

PATCH /v1/projects/:projectId/storage/container-registry/:id/repositories/:repoId

Updates the repository's retention policy. The policy is enforced by the registry itself, so expiry happens on the provider's schedule rather than at push time.

Auth: Required (member, write access, scope: storage:write)

Request Body:

{
  "gcEnabled": true,
  "gcKeepLastN": 10,
  "gcDeleteUntagged": true,
  "gcUntaggedAfterDays": 7,
  "visibility": "PUBLIC",
  "publicEgressCapGb": 50
}

gcKeepLastN accepts 1–1000 and gcUntaggedAfterDays accepts 1–365. At least one field must be provided.

visibility and publicEgressCapGb control anonymous pulls — see Public repositories. Switching to PUBLIC requires a cap, switching to PRIVATE clears it, and either raising the cap or reopening a repository that hit it starts a fresh allowance for the period.

Repositories are returned with publicEgressUsedGb, the anonymous egress served in the current period, and publicEgressCapHitAt, set when a cap closed the repository.

Delete Repository

DELETE /v1/projects/:projectId/storage/container-registry/:id/repositories/:repoId

Auth: Required (member, write access, scope: storage:write)

On this page