---
title: "KYE Protocol™ Status API | API reference"
description: "KYE Protocol™ Status API: 7 operations from status.yaml, a published KYE Protocol™ OpenAPI contract."
url: https://kyeprotocol.com/developers/api/status/
lang: en
source: "KYE Protocol"
---

> KYE Protocol™ Status API: 7 operations from status.yaml, a published KYE Protocol™ OpenAPI contract.

API reference

# KYE Protocol™ Status API

7 operations · `status.yaml`

**Servers**

`https://status.kyeprotocol.com`

**Version**

1.0.0

**Source**

[status.yaml](https://kyeprotocol.com/developers/api/status.yaml)

Public status surface for status.kyeprotocol.com (Cloudflare Pages Functions). No authentication — this is the status page everyone checks when something is down. Per constitution §35 STREAMING-LOGS the incident data is written event-driven by the runtime (the kye-incident-detector Worker when a §13 Resilience Loop drift event crosses a severity threshold), never hand-edited; these endpoints read the canonical D1 tables and serve cached JSON / RSS views.

Status 3 Subscriptions 4

## Status

GET `/api/components` Aggregated component-status report

Returns a kye.status.report.v1 payload aggregated from the canonical component inventory, recent health rows in D1 (kye\_status\_components), and unresolved incidents (kye\_status\_incidents). Overall status is the worst-case of all components. Served through a 60-second KV cache to prevent thundering-herd polling; the x-cache response header reports HIT or MISS. CORS-open (Access-Control-Allow-Origin: \*) so any surface can embed the status widget.

### Responses

- `200` Status report (cached up to 60s)

GET `/api/incidents` Live incident list

Reads the canonical incidents D1 table (event-driven writes per §35 — never hand-edited) and returns a filterable JSON list, newest first, with a 15-second edge cache.

### Parameters

| name | in | type | description |
| --- | --- | --- | --- |
| `limit` | query | integer |  |
| `since` | query | string | Only incidents with started\_at >= this ISO timestamp |
| `component` | query | string | Filter by component\_id |
| `status` | query | string | Filter by incident severity state |

### Responses

- `200` Incident list
- `500` query\_failed — the D1 read raised
- `503` db\_binding\_missing — KYE\_DB not bound on the Pages project

GET `/feed.xml` RSS 2.0 incident feed

RSS 2.0 feed of the 50 most recent incidents, regenerated on each request from the live incidents D1 table with a 60-second edge cache. Per §35, downstream consumers (RSS readers, status aggregators, on-call channels) subscribe to this feed instead of polling the HTML page. If the D1 read fails the endpoint emits an empty but valid feed rather than a 5xx — status RSS is critical infrastructure.

### Responses

- `200` RSS 2.0 XML document

## Subscriptions

GET `/api/subscribe` Describe the subscribe contract

Self-describing helper — returns the expected POST body shape for /api/subscribe (field names, requiredness, semantics) so the form and third-party integrators can introspect the contract without reading source.

### Responses

- `200` Machine-readable description of the POST contract

POST `/api/subscribe` Subscribe to incident + maintenance notifications

Stores a subscription row in D1 (status\_subscriptions, migration 013) and sends a confirmation email through the canonical §38 Comms Engine template status.subscribe.confirmation.v1. Idempotent — an email that is already subscribed returns the existing subscription id with already\_subscribed: true instead of creating a duplicate. Spam controls: a honeypot field (website) silently accepts and ignores bot submissions, and submissions are rate-limited to 5 per day-salted IP hash per 24h window.

### Request body (required)

| field | type | description |
| --- | --- | --- |
| `email` **required** | string |  |
| `accept` **required** | boolean | Must be true — privacy + transactional-email acceptance |
| `components` | array | Optional component-id filter; empty or missing = all components |
| `consent_marketing` | boolean | Opts into the quarterly status digest |

### Responses

- `200` Subscribed (or already subscribed — idempotent)
- `400` invalid\_body, invalid\_email, or terms\_not\_accepted
- `429` rate\_limited — more than 5 subscriptions from the same IP hash in 24h
- `500` handler\_exception — unexpected failure (message included, truncated to 500 chars)
- `503` not\_provisioned — KYE\_DB unbound or migration 013\_status\_subscriptions.sql not applied

OPTIONS `/api/subscribe` CORS preflight

CORS preflight for the subscribe form. Allows origin https://status.kyeprotocol.com with methods GET, POST, OPTIONS and the content-type request header; preflight result cacheable for 86400 seconds.

### Responses

- `204` Preflight accepted (no body)

GET `/api/status/unsubscribe` One-click unsubscribe

One-click unsubscribe for status notifications, linked from every status.subscribe.confirmation.v1 email (RFC 8058 spirit — GET by design, since the link is clicked straight from an email client and the id token is an unguessable kye:status-sub:<uuid>). Idempotent: re-hitting an already-unsubscribed token returns ok: true with already: true. The suppression is recorded to the audit chain (event\_family internal.status.unsubscribe) when AUDIT\_CHAIN\_BASE\_URL is configured; emission failures are logged loudly, never swallowed.

### Parameters

| name | in | type | description |
| --- | --- | --- | --- |
| `id` **required** | query | string | Subscription id token from the email's unsubscribe link |

### Responses

- `200` Unsubscribed (idempotent)
- `400` missing\_token — id absent or not a kye:status-sub:<uuid>
- `404` unknown\_token — no live subscription with that id
- `500` handler\_exception — unexpected failure
- `503` not\_provisioned — KYE\_DB unbound or migration 013\_status\_subscriptions.sql not applied
