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

# Storage API: Manage Private S3 Buckets

> REST endpoints to create, configure, and delete private S3 buckets in your AWS account, and retrieve storage metrics and cost estimates.

The Storage API lets you create and manage private S3 buckets that live directly in your AWS account. Buckets are private by default and are accessible to your web servers and workers through IAM role permissions that Springwinter manages for you. Use these endpoints to provision buckets, update their configuration, review CloudWatch storage metrics, and estimate AWS costs.

## List Buckets

**GET /api/projects/{project_id}/storage**

Return all storage buckets that exist within the specified project.

<CodeGroup>
  ```bash Request theme={null}
  curl https://springwinter.dev/api/projects/proj_abc123/storage \
    -H "Authorization: Bearer swt_yourtoken"
  ```

  ```json Response theme={null}
  {
    "buckets": [
      {
        "id": "stor_def456",
        "name": "my-bucket",
        "arn": "arn:aws:s3:::my-bucket-proj-abc123",
        "region": "us-east-1",
        "status": "active",
        "created_at": "2025-01-15T11:00:00Z",
        "updated_at": "2025-01-15T11:02:10Z"
      }
    ]
  }
  ```
</CodeGroup>

<ResponseField name="buckets" type="array">
  Array of bucket objects for the project. Each object has the same shape as the single-bucket GET response.
</ResponseField>

***

## Create a Bucket

**POST /api/projects/{project_id}/storage**

Create a new private S3 bucket inside the specified project.

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST https://springwinter.dev/api/projects/proj_abc123/storage \
    -H "Authorization: Bearer swt_yourtoken" \
    -H "Content-Type: application/json" \
    -d '{ "name": "my-bucket" }'
  ```

  ```json Response theme={null}
  {
    "id": "stor_def456",
    "name": "my-bucket",
    "arn": "arn:aws:s3:::my-bucket-proj-abc123",
    "region": "us-east-1",
    "status": "creating",
    "created_at": "2025-01-15T11:00:00Z"
  }
  ```
</CodeGroup>

<ParamField body="name" type="string" required>
  A human-readable label for the bucket. Springwinter appends a unique suffix to the actual S3 bucket name to prevent global naming collisions.
</ParamField>

<ResponseField name="id" type="string">Unique Springwinter identifier for this storage resource.</ResponseField>
<ResponseField name="name" type="string">The label you provided at creation time.</ResponseField>
<ResponseField name="arn" type="string">The full Amazon Resource Name of the S3 bucket.</ResponseField>
<ResponseField name="region" type="string">AWS region where the bucket was created, matching your project's region.</ResponseField>
<ResponseField name="status" type="string">Lifecycle state. One of `creating`, `active`, or `deleting`.</ResponseField>

***

## Get a Bucket

**GET /api/projects/{project_id}/storage/{id}**

Return the name, region, ARN, and current status of a bucket.

<CodeGroup>
  ```bash Request theme={null}
  curl https://springwinter.dev/api/projects/proj_abc123/storage/stor_def456 \
    -H "Authorization: Bearer swt_yourtoken"
  ```

  ```json Response theme={null}
  {
    "id": "stor_def456",
    "name": "my-bucket",
    "arn": "arn:aws:s3:::my-bucket-proj-abc123",
    "region": "us-east-1",
    "status": "active",
    "created_at": "2025-01-15T11:00:00Z",
    "updated_at": "2025-01-15T11:02:10Z"
  }
  ```
</CodeGroup>

<ResponseField name="id" type="string">Unique storage resource identifier.</ResponseField>
<ResponseField name="name" type="string">Human-readable bucket label.</ResponseField>
<ResponseField name="arn" type="string">Full S3 ARN, usable in IAM policies and SDK calls.</ResponseField>
<ResponseField name="region" type="string">AWS region of the bucket.</ResponseField>
<ResponseField name="status" type="string">Current lifecycle state of the bucket.</ResponseField>

***

## Update a Bucket

**PATCH /api/projects/{project_id}/storage/{id}**

Update the display name or other mutable settings of an existing bucket. The underlying S3 bucket name does not change.

<CodeGroup>
  ```bash Request theme={null}
  curl -X PATCH https://springwinter.dev/api/projects/proj_abc123/storage/stor_def456 \
    -H "Authorization: Bearer swt_yourtoken" \
    -H "Content-Type: application/json" \
    -d '{ "name": "uploads-bucket" }'
  ```

  ```json Response theme={null}
  {
    "id": "stor_def456",
    "name": "uploads-bucket",
    "arn": "arn:aws:s3:::my-bucket-proj-abc123",
    "region": "us-east-1",
    "status": "active"
  }
  ```
</CodeGroup>

<ParamField body="name" type="string">
  Updated display label for the bucket. Only the Springwinter label changes — the actual S3 bucket name in AWS remains unchanged.
</ParamField>

***

## Delete a Bucket

**DELETE /api/projects/{project_id}/storage/{id}**

Permanently delete a bucket and all of its contents.

<Warning>
  Deleting a bucket removes **all objects inside it** permanently. This action cannot be undone and there is no recovery path. Ensure you have backed up any data you need before calling this endpoint.
</Warning>

<CodeGroup>
  ```bash Request theme={null}
  curl -X DELETE https://springwinter.dev/api/projects/proj_abc123/storage/stor_def456 \
    -H "Authorization: Bearer swt_yourtoken"
  ```

  ```json Response theme={null}
  {
    "id": "stor_def456",
    "status": "deleting"
  }
  ```
</CodeGroup>

***

## Get Storage Metrics

**GET /api/projects/{project_id}/storage/{id}/metrics**

Return CloudWatch metrics for the bucket, including request counts and data transfer volume.

<CodeGroup>
  ```bash Request theme={null}
  curl https://springwinter.dev/api/projects/proj_abc123/storage/stor_def456/metrics \
    -H "Authorization: Bearer swt_yourtoken"
  ```

  ```json Response theme={null}
  {
    "get_requests": 14832,
    "put_requests": 2047,
    "delete_requests": 103,
    "bytes_downloaded": 10737418240,
    "bytes_uploaded": 2147483648,
    "period_seconds": 86400
  }
  ```
</CodeGroup>

<ResponseField name="get_requests" type="integer">Number of GET and HEAD requests in the reporting period.</ResponseField>
<ResponseField name="put_requests" type="integer">Number of PUT, POST, and COPY requests in the reporting period.</ResponseField>
<ResponseField name="delete_requests" type="integer">Number of DELETE requests in the reporting period.</ResponseField>
<ResponseField name="bytes_downloaded" type="integer">Total bytes transferred out of the bucket.</ResponseField>
<ResponseField name="bytes_uploaded" type="integer">Total bytes written into the bucket.</ResponseField>
<ResponseField name="period_seconds" type="integer">Length of the reporting window in seconds.</ResponseField>

***

## Get Storage Cost Estimate

**GET /api/projects/{project_id}/storage/{id}/cost**

Returns a link to the AWS Cost Explorer page for this specific bucket so you can inspect spend with full AWS-native detail.

<CodeGroup>
  ```bash Request theme={null}
  curl https://springwinter.dev/api/projects/proj_abc123/storage/stor_def456/cost \
    -H "Authorization: Bearer swt_yourtoken"
  ```

  ```json Response theme={null}
  {
    "cost_explorer_url": "https://us-east-1.console.aws.amazon.com/cost-management/home#/custom?...",
    "estimated_monthly_usd": 4.27,
    "month_to_date_usd": 1.42,
    "currency": "USD"
  }
  ```
</CodeGroup>

<ResponseField name="cost_explorer_url" type="string">
  A direct URL to AWS Cost Explorer pre-filtered for this bucket. Open it in your browser while logged in to your AWS account.
</ResponseField>

<ResponseField name="estimated_monthly_usd" type="number">
  Springwinter's projection of the full-month cost based on current usage, sourced from AWS Cost Explorer.
</ResponseField>

<ResponseField name="month_to_date_usd" type="number">
  Actual AWS spend recorded so far this calendar month.
</ResponseField>

<ResponseField name="currency" type="string">
  Currency code for all cost values. Always `"USD"`.
</ResponseField>

***

<Note>
  Buckets are private by default and cannot be made public through the Storage API. If you need to serve files publicly over HTTPS, create a **static website** resource instead — Springwinter will provision an S3 bucket and CloudFront distribution configured for public access.
</Note>
