> For the complete documentation index, see [llms.txt](https://docs.visualsentinel.com/llms.txt)

# Public API

Unauthenticated public endpoints (blog, status pages). This page lists all 9 endpoints in the Public area of the Visual Sentinel REST API.

Base URL: `https://visualsentinel.com`. Unless an endpoint says otherwise it accepts an API key or a session cookie, see [Authentication](https://docs.visualsentinel.com/guides/authentication.md). Most error responses use the [ErrorResponse](https://docs.visualsentinel.com/reference/models/error-response.md) shape, see [Errors](https://docs.visualsentinel.com/guides/errors.md) and [Rate limits](https://docs.visualsentinel.com/guides/rate-limits.md).

## Endpoints

- [Submit contact form](#submit-contact-form): `POST /api/contact`
- [Get active announcement](#get-public-announcement): `GET /api/public/announcement`
- [List blog posts](#list-blog-posts): `GET /api/public/blog`
- [Get blog post](#get-blog-post): `GET /api/public/blog/{slug}`
- [Get public status page](#get-public-status-page): `GET /api/public/status/{slug}`
- [Get status badge](#get-status-badge): `GET /api/public/status/{slug}/badge`
- [Subscribe to status updates](#subscribe-to-status-page): `POST /api/public/status/{slug}/subscribe`
- [Unsubscribe from status updates](#unsubscribe-from-status-page): `DELETE /api/public/status/{slug}/subscribe`
- [Verify status page subscription](#verify-status-subscription): `GET /api/public/status/{slug}/verify`

## Submit contact form

`POST /api/contact`

Submit a contact form message. No authentication required.

Authentication: no session or API key needed.

Request body (required): object.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes |   |
| `email` | string (email) | Yes |   |
| `subject` | string | No |   |
| `message` | string | Yes |   |

**Responses**

- `200`: Message sent.

## Get active announcement

`GET /api/public/announcement`

Returns the currently active site announcement (promotional banners, maintenance notices, etc.). Cached for 60 seconds. No authentication required. Falls back to environment-based discount config if no database announcement is active.

Authentication: no session or API key needed.

**Parameters**

- `context` (query, string, optional): Filter announcements by display context One of: `public`, `dashboard`, `checkout`. Default: `public`.

**Responses**

- `200`: Active announcement or null. Body: object or null.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | No |   |
| `type` | string | No | One of: `PROMO`, `MAINTENANCE`, `INFO`, `WARNING`. |
| `message` | string | No |   |
| `active` | boolean | No |   |
| `discountId` | string or null | No |   |
| `discountPercent` | number or null | No |   |
| `bgColor` | string or null | No |   |
| `textColor` | string or null | No |   |
| `icon` | string or null | No |   |
| `showOnPublic` | boolean | No |   |
| `showOnDashboard` | boolean | No |   |
| `showOnCheckout` | boolean | No |   |

## List blog posts

`GET /api/public/blog`

Get published blog posts with pagination.

Authentication: no session or API key needed.

**Parameters**

- `page` (query, integer, optional): Default: `1`.
- `limit` (query, integer, optional): Default: `10`.
- `category` (query, string, optional)

**Responses**

- `200`: Blog posts.

## Get blog post

`GET /api/public/blog/{slug}`

Get a single blog post by slug.

Authentication: no session or API key needed.

**Parameters**

- `slug` (path, string, required)

**Responses**

- `200`: Blog post.
- `404`: Post not found.

## Get public status page

`GET /api/public/status/{slug}`

Get a public status page by slug (no auth required).

Authentication: no session or API key needed.

**Parameters**

- `slug` (path, string, required)

**Responses**

- `200`: Public status page data.
- `404`: Status page not found.

## Get status badge

`GET /api/public/status/{slug}/badge`

Get an SVG status badge for embedding in README files or websites.

Authentication: no session or API key needed.

**Parameters**

- `slug` (path, string, required)

**Responses**

- `200`: SVG badge. Body: string (`image/svg+xml`).

## Subscribe to status updates

`POST /api/public/status/{slug}/subscribe`

Subscribe an email address to status page updates.

Authentication: no session or API key needed.

**Parameters**

- `slug` (path, string, required)

Request body (required): object.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `email` | string (email) | Yes |   |

**Responses**

- `200`: Subscribed (verification email sent)

## Unsubscribe from status updates

`DELETE /api/public/status/{slug}/subscribe`

Unsubscribe from status page updates.

Authentication: no session or API key needed.

**Parameters**

- `slug` (path, string, required)

**Responses**

- `200`: Unsubscribed.

## Verify status page subscription

`GET /api/public/status/{slug}/verify`

Verify email subscription to a status page using the verification token.

Authentication: no session or API key needed.

**Parameters**

- `slug` (path, string, required)
- `token` (query, string, required)

**Responses**

- `200`: Subscription verified.

Generated from the OpenAPI 3.1 specification at [https://docs.visualsentinel.com/openapi.json](https://docs.visualsentinel.com/openapi.json), the same file the interactive reference reads.
