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

# Create Status Page

> Create a status page that shows the live status of selected monitors

## Overview

Creates a status page in a project. New pages start as a **draft** (not public) unless you send `status: "published"`. Call [Publish Status Page](/api-reference/status-pages/publish) when you are ready to make a draft page visible.

`POST /api/projects/{projectId}/status-pages`

## Authentication

| Header | Required | Description |
| - | - | - |
| `X-API-Key` | Yes | Your API key (`Authorization: Bearer {jwt}` also works). API keys need the `read_write` scope. |
| `X-Project-ID` | Yes | Must be the same project UUID as in the URL. |
| `Content-Type` | Yes | `application/json` |

**Required access:** project admin. Other members receive `INSUFFICIENT_PERMISSIONS`.

## Path parameters

| Parameter | Type | Description |
| - | - | - |
| `projectId` | UUID | Project that will own the status page |

## Request body

| Field | Type | Required | Description |
| - | - | - | - |
| `name` | string | Yes | Display name, 1-255 characters |
| `description` | string | No | Short description shown on the page |
| `subdomain` | string | No | 3-63 characters: lowercase letters, numbers and single hyphens (no leading or trailing hyphen). Must be unique and not reserved. If omitted, one is generated from `name`. **Cannot be changed later.** Use [Check Subdomain](/api-reference/status-pages/check-subdomain) first. |
| `monitor_ids` | UUID\[] | Yes | At least one monitor from the same project |
| `monitor_options` | object\[] | No | Per-monitor labels. See [Monitor options](#monitor-options) |
| `status` | string | No | Initial publication state: `draft` (default) or `published`. `archived` is not accepted at creation. |
| `branding` | object | No | See [Branding object](#branding-object) |
| `settings` | object | No | See [Settings object](#settings-object) |

### Monitor options

Optional labels for monitors listed in `monitor_ids`. Display order still follows `monitor_ids`; monitors without an entry get no label and no group.

| Field | Type | Required | Description |
| - | - | - | - |
| `monitor_id` | UUID | Yes | Must also appear in `monitor_ids`. Each monitor may appear only once. |
| `display_name` | string \| null | No | Name shown on the page instead of the monitor name. Up to 255 characters, trimmed; an empty string is stored as `null`. |
| `group_name` | string \| null | No | Group heading the monitor is shown under. Up to 100 characters, trimmed; an empty string is stored as `null`. |

The request is rejected with `400 VALIDATION_ERROR` if a `monitor_id` is not in `monitor_ids`, if the same `monitor_id` appears more than once, or if a label exceeds its length limit.

### Branding object

Keys may be sent in camelCase (recommended) or the older snake\_case spelling (`logo_url`, `primary_color`, ...). Responses always use camelCase.

| Field | Type | Description |
| - | - | - |
| `defaultTheme` | string | `light`, `dark` or `system`. The legacy key `theme` is accepted for this field. |
| `logoUrl` | string \| null | Valid URL |
| `faviconUrl` | string \| null | Valid URL |
| `primaryColor` | string | Hex colour in `#RRGGBB` form |
| `showUptimeGraphs` | boolean | Show uptime graphs |
| `showResponseTimes` | boolean | Show response-time charts |
| `customCss` | string \| null | Up to 10,000 characters. The CSS is sanitised before it is stored: external URLs and unsafe constructs are removed. |

Use the [Branding endpoint](/api-reference/status-pages/branding) for the full set of colours, images and company details.

### Settings object

| Field | Type | Default | Description |
| - | - | - | - |
| `incident_history_days` | integer | `7` | Days of incident history shown (1-365) |
| `uptime_timeframes` | string\[] | `["24h","7d","30d","90d"]` | Uptime windows shown on the page |
| `timezone` | string | `"UTC"` | Timezone used to display times |
| `show_powered_by` | boolean | `true` | Show the "Powered by UptimeIO" badge. Setting `false` requires the **Scale** plan. |
| `maintenance_affects_uptime` | boolean | `false` | Whether maintenance windows count against uptime |
| `uptime_thresholds` | object | `{"operational":99.9,"degraded":95}` | Both values are numbers from 0 to 100 |
| `allow_search_indexing` | boolean | `true` | Allow search engines to index the page |
| `google_analytics_id` | string \| null | `null` | Google Analytics 4 measurement ID, `G-` followed by 4-12 uppercase letters or digits (for example `G-ABCD123456`) |
| `show_agent_locations` | boolean | `false` | Show probe locations |

## Plan limits

| Plan | Status pages | Custom domain | Remove "Powered by" |
| - | - | - | - |
| Free | 1 | No | No |
| Pro | 20 | Yes | No |
| Scale | 100 | Yes | Yes |

Custom CSS, logo and favicon are available on every plan.

## Response

### 201 Created

```json theme={null}
{
  "success": true,
  "data": {
    "status_page": {
      "id": "0b7c3a52-7d57-4c35-9f0e-5a3b6f1f2a10",
      "organization_id": "4f6f7b0e-1a52-4d7f-8d7e-6c5b1d2e3f40",
      "project_id": "6ba7b810-9dad-41d1-80b4-00c04fd430c8",
      "name": "Production Status",
      "description": "Live status of production services",
      "subdomain": "acme-production",
      "status": "draft",
      "is_public": false,
      "color_scheme": "light",
      "logo_url": null,
      "favicon_url": null,
      "custom_css": null,
      "component_display_order": "custom",
      "show_uptime_percentage": true,
      "show_response_time": true,
      "timezone": "UTC",
      "allow_search_indexing": true,
      "uptime_timeframes": ["24h", "7d", "30d", "90d"],
      "uptime_thresholds": { "operational": 99.9, "degraded": 95 },
      "incident_history_days": 7,
      "maintenance_affects_uptime": false,
      "google_analytics_id": null,
      "custom_domain": null,
      "custom_domain_verified": false,
      "ssl_enabled": false,
      "ssl_certificate_status": null,
      "auto_publish_enabled": true,
      "auto_publish_severities": ["critical", "major"],
      "subscriber_count": 0,
      "monitor_count": 0,
      "page_views_24h": 0,
      "page_views_7d": 0,
      "page_views_30d": 0,
      "last_published_at": null,
      "created_by": null,
      "created_at": 1790000000000,
      "updated_at": 1790000000000,
      "branding": {
        "defaultTheme": "light",
        "primaryColor": "#0066CC"
      }
    },
    "public_url": "https://acme-production.status.uptimeio.com"
  }
}
```

The status page object is described on [Get Status Page](/api-reference/status-pages/get#the-status-page-object). Timestamps are Unix milliseconds. `monitor_count` is `0` in this response; fetch the page to see its monitors. `public_url` is the page's verified custom domain when it has one.

## Errors

| Status | Code | Cause |
| - | - | - |
| 400 | `VALIDATION_ERROR` | Body failed validation, or the subdomain is malformed, reserved or already in use. `google_analytics_id` must match the `G-XXXXXXXX` format. This includes `monitor_options` entries whose `monitor_id` is not in `monitor_ids` or is duplicated. The message lists each failing field. |
| 400 | `PROJECT_ID_REQUIRED` / `INVALID_PROJECT_ID` | `X-Project-ID` header missing or not a UUID |
| 401 | `AUTHENTICATION_REQUIRED` | Missing or invalid credentials |
| 403 | `INSUFFICIENT_PERMISSIONS` | Caller is not a project admin |
| 403 | `STATUS_PAGE_LIMIT_REACHED` | Your plan's status page limit is reached |
| 403 | `FEATURE_NOT_AVAILABLE` | `show_powered_by: false` on a plan below Scale |
| 403 | `API_KEY_ORGANIZATION_MISMATCH` | The API key belongs to a different organization than the project |
| 403 | `READ_ONLY_API_KEY` | The API key has the `read` scope |
| 404 | `RESOURCE_NOT_FOUND` | A monitor does not exist or is not in this project |

## Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.uptimeio.com/api/projects/YOUR_PROJECT_ID/status-pages \
    -H "X-API-Key: YOUR_API_KEY" \
    -H "X-Project-ID: YOUR_PROJECT_ID" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Production Status",
      "description": "Live status of production services",
      "subdomain": "acme-production",
      "monitor_ids": ["YOUR_MONITOR_ID"],
      "monitor_options": [
        { "monitor_id": "YOUR_MONITOR_ID", "display_name": "Public API", "group_name": "Core" }
      ],
      "branding": { "defaultTheme": "light", "primaryColor": "#0066CC" },
      "settings": { "timezone": "America/New_York", "incident_history_days": 30 }
    }'
  ```

  ```javascript JavaScript theme={null}
  const projectId = 'YOUR_PROJECT_ID';

  const response = await fetch(
    `https://api.uptimeio.com/api/projects/${projectId}/status-pages`,
    {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.UPTIMEIO_API_KEY,
        'X-Project-ID': projectId,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        name: 'Production Status',
        monitor_ids: ['YOUR_MONITOR_ID'],
      }),
    }
  );

  const { data } = await response.json();
  console.log(data.public_url);
  ```
</CodeGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.