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

# Get Site

> Check a site's status, latest run, and findings summary

## GET /api/static/sites/:id

Retrieve a single [Site's](/guides/sites) status, its latest scan run, and a summary of current security findings.

Requires an API key with the `read` scope (a `read-and-scan` key also works, since `read-and-scan` implies `read`).

### Request

**Headers:**

* `x-api-key` (required): Your Rafter security API key, scope `read` or `read-and-scan`

**Path Parameters:**

| Parameter | Type   | Required | Description                |
| --------- | ------ | -------- | -------------------------- |
| `id`      | string | Yes      | The site's id (project id) |

### Example Request

```bash theme={null}
curl -H "x-api-key: RFabc-your-api-key-here" \
  https://rafter.so/api/static/sites/b1b2c3d4-e5f6-7890-abcd-ef1234567890
```

### Response

**Success (200 OK):**

```json theme={null}
{
  "site": {
    "id": "b1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "registrable_domain": "example.com",
    "preferred_base_url": "https://example.com",
    "scope_type": "domain",
    "scope_value": "example.com",
    "is_archived": false,
    "created_at": "2026-07-24T00:00:00.000+00:00"
  },
  "latest_run": {
    "id": "r_1a2b3c4d",
    "status": "failed",
    "progress_total": 12,
    "progress_done": 12,
    "started_at": "2026-07-24T00:01:00.000+00:00",
    "finished_at": "2026-07-24T00:04:30.000+00:00",
    "created_at": "2026-07-24T00:00:00.000+00:00",
    "step_counts": {
      "queued": 0,
      "running": 0,
      "succeeded": 11,
      "failed": 1
    },
    "progress_percent": 100
  },
  "security": {
    "critical": 1,
    "warn": 3,
    "info": 5,
    "total": 9
  }
}
```

**No runs yet (`latest_run` is `null`):**

```json theme={null}
{
  "site": {
    "id": "b1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "registrable_domain": "example.com",
    "preferred_base_url": "https://example.com",
    "scope_type": "domain",
    "scope_value": "example.com",
    "is_archived": false,
    "created_at": "2026-07-24T00:00:00.000+00:00"
  },
  "latest_run": null,
  "security": {
    "critical": 0,
    "warn": 0,
    "info": 0,
    "total": 0
  }
}
```

**Error (401 Unauthorized):**

```json theme={null}
{
  "error": "Invalid or inactive API key."
}
```

**Error (404 Not Found — not owned or doesn't exist):**

```json theme={null}
{
  "error": "Site not found."
}
```

**Error (429 Too Many Requests):**

```json theme={null}
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Please try again later.",
  "retryAfter": 30
}
```

**Error (500 Internal Server Error):**

```json theme={null}
{
  "error": "An unexpected error occurred."
}
```

### Response Fields

| Field                         | Type           | Description                                                              |
| ----------------------------- | -------------- | ------------------------------------------------------------------------ |
| `site.id`                     | string         | Unique identifier for the site                                           |
| `site.registrable_domain`     | string         | The site's registrable domain                                            |
| `site.preferred_base_url`     | string         | The canonical base URL used for scanning                                 |
| `site.scope_type`             | string         | How the site's scan scope is defined                                     |
| `site.scope_value`            | string         | The value for `scope_type`                                               |
| `site.is_archived`            | boolean        | Whether the site has been archived                                       |
| `site.created_at`             | string         | ISO 8601 timestamp when the site was created                             |
| `latest_run`                  | object \| null | The most recent scan run, or `null` if the site has never been scanned   |
| `latest_run.id`               | string         | Unique identifier for the run                                            |
| `latest_run.status`           | string         | Run status                                                               |
| `latest_run.progress_total`   | integer        | Total number of steps in the run                                         |
| `latest_run.progress_done`    | integer        | Number of steps completed so far                                         |
| `latest_run.started_at`       | string \| null | ISO 8601 timestamp when the run started                                  |
| `latest_run.finished_at`      | string \| null | ISO 8601 timestamp when the run finished                                 |
| `latest_run.created_at`       | string         | ISO 8601 timestamp when the run was created                              |
| `latest_run.step_counts`      | object         | Count of steps in each state: `queued`, `running`, `succeeded`, `failed` |
| `latest_run.progress_percent` | integer        | Overall run progress, `0`–`100`                                          |
| `security.critical`           | integer        | Number of critical findings                                              |
| `security.warn`               | integer        | Number of warning-level findings                                         |
| `security.info`               | integer        | Number of informational findings                                         |
| `security.total`              | integer        | Total findings across all severities                                     |

## Rate Limiting

The API implements rate limiting to ensure fair usage:

* **Rate Limit**: 100 requests per minute per IP address
* **Quota**: Based on your subscription plan

### Examples

#### JavaScript

```javascript theme={null}
const response = await fetch(
  'https://rafter.so/api/static/sites/b1b2c3d4-e5f6-7890-abcd-ef1234567890',
  { headers: { 'x-api-key': 'RFabc-your-api-key-here' } }
);

const data = await response.json();
console.log(`Status: ${data.latest_run?.status ?? 'no runs yet'}`);
console.log(`Critical findings: ${data.security.critical}`);
```

#### Python

```python theme={null}
import requests

response = requests.get(
    'https://rafter.so/api/static/sites/b1b2c3d4-e5f6-7890-abcd-ef1234567890',
    headers={'x-api-key': 'RFabc-your-api-key-here'}
)

data = response.json()
status = data['latest_run']['status'] if data['latest_run'] else 'no runs yet'
print(f"Status: {status}")
print(f"Critical findings: {data['security']['critical']}")
```
