> ## 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.

# Web Servers API: Deploy and Manage HTTP Services

> Launch, update, redeploy, and monitor containerized HTTP services in your AWS account using the Springwinter Web Servers API.

Web servers are containerized HTTP services that Springwinter runs on Amazon ECS inside your AWS account. Each web server gets a public URL derived from your project's hostname suffix, and Springwinter handles load balancing, TLS termination, auto-scaling, and health checks for you. The endpoints below cover the full lifecycle — from launching a new service to reading live logs, metrics, and cost estimates. All requests require a valid `Authorization: Bearer <token>` header or an active cookie session with a CSRF token.

***

## Launch a Web Server

```http theme={null}
POST /api/projects/{project_id}/web_servers
```

Creates and deploys a new containerized web server into the project. Springwinter pulls the source from the specified GitHub repository branch, builds the container image, pushes it to ECR, and starts the ECS service.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that will own this web server.
</ParamField>

### Body Parameters

<ParamField body="name" type="string" required>
  Display name for the web server. Used in the dashboard and to derive the service subdomain.
</ParamField>

<ParamField body="repo" type="string" required>
  GitHub repository full name in `owner/repo` format (e.g. `acme/storefront`). The Springwinter GitHub App must already be installed on this repository.
</ParamField>

<ParamField body="branch" type="string" required>
  Git branch to build and deploy (e.g. `main`).
</ParamField>

<ParamField body="build_command" type="string">
  Shell command Springwinter runs inside the container build context (e.g. `npm run build`). Omit if your `Dockerfile` handles the build step internally.
</ParamField>

<ParamField body="health_path" type="string" default="/">
  HTTP path the load balancer uses for health checks. Must return `200 OK` for the service to become healthy (e.g. `/healthz`).
</ParamField>

<ParamField body="cpu" type="integer" required>
  ECS task CPU units. Valid values: `256`, `512`, `1024`, `2048`, `4096`.
</ParamField>

<ParamField body="memory" type="integer" required>
  ECS task memory in MiB. Must be a valid combination for the chosen `cpu` value per AWS Fargate sizing rules.
</ParamField>

<ParamField body="auto_deploy" type="boolean" default="false">
  When `true`, Springwinter automatically redeploys the service on every push to the configured branch.
</ParamField>

```json theme={null}
{
  "name": "api",
  "repo": "acme/storefront",
  "branch": "main",
  "build_command": "npm run build",
  "health_path": "/healthz",
  "cpu": 512,
  "memory": 1024,
  "auto_deploy": true
}
```

### Response — `201 Created`

```json theme={null}
{
  "id": "ws_01h8xkr2m4fgz3nvq7p0c5w9",
  "name": "api",
  "status": "deploying",
  "url": "https://api.storefront.springwinter.app",
  "repo": "acme/storefront",
  "branch": "main",
  "health_path": "/healthz",
  "cpu": 512,
  "memory": 1024,
  "auto_deploy": true
}
```

***

## Get a Web Server

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}
```

Returns the current configuration and status of a web server.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Response

```json theme={null}
{
  "id": "ws_01h8xkr2m4fgz3nvq7p0c5w9",
  "name": "api",
  "status": "running",
  "url": "https://api.storefront.springwinter.app",
  "repo": "acme/storefront",
  "branch": "main",
  "health_path": "/healthz",
  "cpu": 512,
  "memory": 1024,
  "auto_deploy": true
}
```

***

## Update a Web Server

```http theme={null}
PATCH /api/projects/{project_id}/web_servers/{id}
```

Updates one or more mutable settings on a running web server. Changing source, compute, or health-path settings triggers an automatic redeploy.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Body Parameters

<ParamField body="branch" type="string">
  Switch deployments to a different Git branch.
</ParamField>

<ParamField body="build_command" type="string">
  Updated build command.
</ParamField>

<ParamField body="health_path" type="string">
  Updated health check path.
</ParamField>

<ParamField body="cpu" type="integer">
  Updated CPU units. Triggers a task-definition replacement and rolling redeploy.
</ParamField>

<ParamField body="memory" type="integer">
  Updated memory in MiB.
</ParamField>

<ParamField body="auto_deploy" type="boolean">
  Enable or disable automatic deployments on push.
</ParamField>

### Response

Returns the updated web server object with `"status": "deploying"` if a redeploy was triggered.

```json theme={null}
{
  "id": "ws_01h8xkr2m4fgz3nvq7p0c5w9",
  "name": "api",
  "status": "deploying",
  "url": "https://api.storefront.springwinter.app",
  "repo": "acme/storefront",
  "branch": "main",
  "health_path": "/healthz",
  "cpu": 1024,
  "memory": 2048,
  "auto_deploy": true
}
```

***

## Delete a Web Server

```http theme={null}
DELETE /api/projects/{project_id}/web_servers/{id}
```

Tears down the ECS service, removes the load balancer target group, and deletes the ECR repository for this web server. This operation is irreversible.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server to delete.
</ParamField>

### Response — `204 No Content`

An empty body on success.

***

## Redeploy a Web Server

```http theme={null}
POST /api/projects/{project_id}/web_servers/{id}/redeploy
```

Triggers an immediate redeploy from the current branch, regardless of whether any new commits exist. Use this to apply environment variable changes or to recover from a failed deployment.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Response — `202 Accepted`

```json theme={null}
{
  "status": "deploying"
}
```

***

## Get Logs

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/logs
```

Returns recent log lines streamed from the CloudWatch log group attached to this ECS service. Lines are returned in chronological order.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Response

```json theme={null}
{
  "lines": [
    {
      "timestamp": "2024-06-01T12:00:01Z",
      "message": "Server listening on port 8080"
    },
    {
      "timestamp": "2024-06-01T12:00:05Z",
      "message": "GET /healthz 200 2ms"
    }
  ]
}
```

***

## Get Metrics

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/metrics
```

Returns CloudWatch metrics for the web server including CPU utilization, memory utilization, request count, and error rate.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Response

```json theme={null}
{
  "cpu_utilization_percent": 18.4,
  "memory_utilization_percent": 42.1,
  "request_count_1h": 14823,
  "error_rate_percent": 0.12
}
```

***

## Get Cost Estimate

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/cost
```

Returns the estimated spend to date this month and the projected monthly run rate for this web server based on current ECS task sizes and uptime.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Response

```json theme={null}
{
  "spend_this_month_usd": 4.27,
  "monthly_run_rate_usd": 14.50,
  "currency": "USD"
}
```

***

## Get Environment Variables

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/environment
```

Returns the current set of ECS task environment variables configured for this web server.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Response

```json theme={null}
{
  "environment": [
    { "name": "NODE_ENV", "value": "production" },
    { "name": "DATABASE_URL", "value": "postgres://user:pass@db.storefront.springwinter.app/app" }
  ]
}
```

***

## Replace Environment Variables

```http theme={null}
PUT /api/projects/{project_id}/web_servers/{id}/environment
```

Replaces the complete set of ECS task environment variables for this web server and triggers a rolling redeploy so the new values take effect.

### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

### Body Parameters

<ParamField body="environment" type="array" required>
  Array of `{ "name": string, "value": string }` objects. This list fully replaces the existing environment — any variable not included in the request is removed.
</ParamField>

<Warning>
  This endpoint performs a full replacement, not a merge. Any environment variable you omit from the request body will be permanently deleted. Fetch the current environment with `GET .../environment` first, merge your changes, and then submit the complete list.
</Warning>

```json theme={null}
{
  "environment": [
    { "name": "NODE_ENV", "value": "production" },
    { "name": "DATABASE_URL", "value": "postgres://user:pass@db.storefront.springwinter.app/app" },
    { "name": "REDIS_URL", "value": "rediss://cache.storefront.springwinter.app:6379" }
  ]
}
```

### Response — `202 Accepted`

```json theme={null}
{
  "status": "deploying"
}
```

***

## Previews

Each web server can have multiple branch preview deployments. Every preview gets its own isolated URL, environment variables, and ECS task — it does not share compute with the production deployment.

### Create a Preview

```http theme={null}
POST /api/projects/{project_id}/web_servers/{id}/previews
```

Creates and deploys a new preview for the specified branch.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

#### Body Parameters

<ParamField body="branch" type="string" required>
  The Git branch to build and deploy as a preview.
</ParamField>

```json theme={null}
{ "branch": "feat/checkout-redesign" }
```

**Response — `201 Created`**

```json theme={null}
{
  "id": "prev_03k0zmr4o6hic5pws9r2e7y1",
  "branch": "feat/checkout-redesign",
  "url": "https://api-feat-checkout-redesign.storefront.springwinter.app",
  "status": "deploying"
}
```

***

### Get a Preview

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/previews/{preview_id}
```

Returns the preview object including its URL and current status.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "id": "prev_03k0zmr4o6hic5pws9r2e7y1",
  "branch": "feat/checkout-redesign",
  "url": "https://api-feat-checkout-redesign.storefront.springwinter.app",
  "status": "running"
}
```

***

### Delete a Preview

```http theme={null}
DELETE /api/projects/{project_id}/web_servers/{id}/previews/{preview_id}
```

Tears down the preview ECS service and removes all associated AWS resources.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment to delete.
</ParamField>

#### Response — `204 No Content`

An empty body on success.

***

### Preview Logs

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/previews/{preview_id}/logs
```

Returns CloudWatch log lines for the preview deployment in the same format as the main service logs endpoint.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "lines": [
    {
      "timestamp": "2024-06-01T15:00:03Z",
      "message": "Server listening on port 8080"
    },
    {
      "timestamp": "2024-06-01T15:00:11Z",
      "message": "GET /healthz 200 3ms"
    }
  ]
}
```

***

### Preview Metrics

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/previews/{preview_id}/metrics
```

Returns CPU, memory, request, and error metrics for the preview deployment.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "cpu_utilization_percent": 9.1,
  "memory_utilization_percent": 37.4,
  "request_count_1h": 312,
  "error_rate_percent": 0.0
}
```

***

### Preview Environment Variables

```http theme={null}
GET /api/projects/{project_id}/web_servers/{id}/previews/{preview_id}/environment
```

Returns the environment variables configured for this specific preview deployment.

#### Path Parameters

<ParamField path="project_id" type="string" required>
  The ID of the project that owns the web server.
</ParamField>

<ParamField path="id" type="string" required>
  The unique ID of the web server.
</ParamField>

<ParamField path="preview_id" type="string" required>
  The unique ID of the preview deployment.
</ParamField>

#### Response

```json theme={null}
{
  "environment": [
    { "name": "NODE_ENV", "value": "preview" },
    { "name": "DATABASE_URL", "value": "postgres://user:pass@db.storefront.springwinter.app/app_preview" }
  ]
}
```

<Tip>
  Preview environments inherit the parent web server's environment variables by default. Use this endpoint to confirm what a specific preview is running with, or to diagnose configuration drift between branches.
</Tip>
