---
title: "KYE Protocol™ Admin Root Endpoints | API reference"
description: "KYE Protocol™ Admin Root Endpoints: 3 operations from admin-root.yaml, a published KYE Protocol™ OpenAPI contract."
url: https://kyeprotocol.com/developers/api/admin-root/
lang: en
source: "KYE Protocol"
---

> KYE Protocol™ Admin Root Endpoints: 3 operations from admin-root.yaml, a published KYE Protocol™ OpenAPI contract.

API reference

# KYE Protocol™ Admin Root Endpoints

3 operations · `admin-root.yaml`

**Servers**

`https://admin.kyeprotocol.com`

**Version**

1.0.0

**Source**

[admin-root.yaml](https://kyeprotocol.com/developers/api/admin-root.yaml)

Root-level (non-/api/v1) endpoints on admin.kyeprotocol.com. These are NOT Clerk-session endpoints: /email-action is authenticated by a signed single-use email-action token in the request itself (constitution §27 §4 Dual-Channel Admin + §27 §7 Email-Action Token), and /webhooks/stripe is authenticated by Stripe's v1 webhook signature (constitution §27 §8 — Stripe baked in). The /api/v1 owner console is documented separately in admin.yaml.

EmailAction 2 Webhooks 1

## EmailAction

GET `/email-action` Execute a one-click signed email-action token

The single canonical entry point for ALL signed email-action token clicks — commercial-lifecycle, expert-review, consultant approval, key rotation, deploy gate. The flow: (1) verify the token's signature via the canonical email-action-token library; (2) enforce single-use via the `email_action_token_used` D1 table (UNIQUE on token\_hash — a re-click renders an "already taken" page without re-dispatching); (3) resolve the admin domain from the workflow\_id prefix (`kye:commercial-workflow:*`, `kye:expert-review:*`, `kye:consultant:*`, `kye:key-rotation:*`, `kye:deploy-gate:*`, and the other registered prefixes); (4) dispatch — expert-review actions are applied inline as a D1 UPDATE, every other domain is enqueued onto its queue binding for the lifecycle agent; (5) record the use and render a confirmation page. Because these URLs are clicked by humans, every outcome (missing / expired / re-used token, unknown domain, dispatch failure, success) is an HTML page, not a JSON error: 200 for success and already-used, 400 for every failure. Authenticated by the token itself — no bearer auth.

### Parameters

| name | in | type | description |
| --- | --- | --- | --- |
| `token` **required** | query | string | Signed single-use email-action token (opaque signed payload) |

### Responses

- `200` Action recorded (or token already used — original action remains in effect); HTML confirmation page
- `400` Token missing, invalid, expired, or workflow domain unknown; HTML error page

POST `/email-action` Execute an email-action token submitted via form POST

Identical semantics to GET /email-action — the handler delegates POST to the GET logic. POST exists for forms that submit the token in the body rather than the URL, which avoids email-client link rewriting / tracking parameters corrupting the signed GET URL. The token is still read from the `token` query parameter of the submitted form action. Same single-use enforcement, domain dispatch and HTML confirmation/error rendering as GET. Authenticated by the token itself — no bearer auth.

### Parameters

| name | in | type | description |
| --- | --- | --- | --- |
| `token` **required** | query | string | Signed single-use email-action token (opaque signed payload) |

### Responses

- `200` Action recorded (or token already used); HTML confirmation page
- `400` Token missing, invalid, expired, or workflow domain unknown; HTML error page

## Webhooks

POST `/webhooks/stripe` Receive and dispatch Stripe webhook events

Verifies the `Stripe-Signature` header (Stripe's documented v1 Stripe's published webhook-signature scheme (300-second timestamp tolerance), constant-time comparison) against STRIPE\_WEBHOOK\_SIGNING\_SECRET, then translates the event into a commercial-lifecycle transition request enqueued onto KYE\_LIFECYCLE\_QUEUE — the lifecycle agent is the only code path that mutates `commercial_workflows` state. Handled events: invoice.paid / invoice.payment\_succeeded (the ONLY signal that advances a workflow toward access provisioning, §27 §6 payment-gate hard-lock), invoice.payment\_failed (with failure\_code mapped to the canonical taxonomy), invoice.payment\_action\_required (3DS/SCA), invoice.voided, invoice.marked\_uncollectible, charge.refunded, charge.dispute.created, customer.subscription.deleted, plus the read-model-only checkout.session.completed and customer.subscription.updated projections. Unhandled event types are acknowledged with `{ignored: true}` so Stripe does not retry. Authenticated by the Stripe signature — no bearer auth.

### Parameters

| name | in | type | description |
| --- | --- | --- | --- |
| `Stripe-Signature` **required** | header | string | Stripe v1 signature header (t=<unix\_ts>,v1=<hex\_sig>,…) |

### Request body (required)

| field | type | description |
| --- | --- | --- |
| `id` **required** | string |  |
| `type` **required** | string |  |
| `livemode` | boolean |  |
| `data` | object |  |

### Responses

- `200` Event acknowledged — dispatched to the lifecycle queue, or ignored (unhandled type)
- `400` Body is not valid JSON or the event envelope is malformed
- `401` Stripe-Signature header missing, stale, or signature mismatch
- `503` Signing secret unset or queue dispatch failed — Stripe should retry
