Webhooks & API
Agents use MCP. Everything else is a small set of HTTP endpoints.
Endpoints
| Endpoint | Auth | Purpose |
|---|---|---|
POST GET DELETE /api/mcp | Agent key or OAuth access token (Bearer) | MCP Streamable HTTP endpoint for agents. 300 requests per minute per agent. |
POST /api/webhooks/{siteId} | Site webhook token | Receives CMS change events and WordPress plugin events. |
GET /api/w/{workspace}/audit/export | Signed-in admin or owner | Full audit log as JSON, with the integrity check result. |
GET /api/health | None | Returns {"ok":true} when the app and database are reachable, 503 otherwise. |
GET /api/cron/schedules | Bearer CRON_SECRET | Runs due scheduled publishes and ends, site watch and connection checks. Called every minute by Vercel Cron; self-hosted servers run it in-process. |
GET /api/cron/agents | Bearer CRON_SECRET | Sends “agent went quiet” alerts for agents silent longer than their alert setting. Called hourly by Vercel Cron; self-hosted servers run it in-process. |
GET /.well-known/oauth-protected-resource/api/mcp | None | OAuth protected-resource metadata (RFC 9728). |
GET /.well-known/oauth-authorization-server | None | OAuth authorization-server metadata (RFC 8414). |
POST /oauth/register | None | Dynamic client registration (RFC 7591). |
GET /oauth/authorize | Signed-in user | Consent screen: choose workspace and trust level. PKCE S256 required. |
POST /oauth/token | Client (PKCE or secret) | Exchange a code or refresh token. Refresh tokens rotate; reuse is detected. |
POST /oauth/revoke | Client | Token revocation (RFC 7009). |
CMS webhooks
Each site has a webhook URL that tells Lyntcast when content changed outside it. Find it under Sites → Catch edits that skip Lyntcast:
POST https://<your-lyntcast>/api/webhooks/<siteId>?token=<secret>- The secret can be sent as the
tokenquery parameter or thex-lyntcast-tokenheader (x-gatehouse-tokenis also accepted). Wrong or missing tokens get401. - Bodies must be JSON, up to 1 MB (
413above that,400for invalid JSON). - Lyntcast recognises the native payloads of each CMS and extracts the document ID:
| CMS | Payload Lyntcast reads |
|---|---|
| Sanity | _id (drafts are mapped to the published ID), operation from the sanity-operation header |
| Contentful | sys.id, event from x-contentful-topic |
| WordPress | post_id / ID / id and post_type, or plugin events |
| Ghost | post.current.id or page.current.id |
| Strapi | model and entry.documentId |
| Webflow | payload.collectionId and payload.id |
| Shopify | Product id, topic from x-shopify-topic |
Edits Lyntcast made itself are recognised and not reported twice. Other edits appear in the document’s history, and pending changes to the same fields are flagged as conflicts on approval.
Document IDs
Agents and webhooks use the same IDs:
- WordPress:
posts:42,pages:7, WooCommercewc-products:42 - Ghost:
posts:<id>,pages:<id> - Strapi:
<content type>:<documentId> - Webflow:
<collectionId>:<itemId> - Shopify:
products:<id> - Sanity and Contentful: the document or entry ID
Errors from the MCP endpoint
401with aWWW-Authenticate: Bearer resource_metadata=…header when credentials are missing or invalid. OAuth-capable clients use it to start sign-in.429withRetry-After: 60when an agent exceeds 300 requests per minute.- Tool errors (paused agent, daily limit, outdated version, unknown site, content outside the agent’s scope, an idempotency key reused for a different change) come back as MCP tool results with a plain-language message for the agent.
- A repeated
propose_change(sameidempotency_key, or an identical proposal within 10 minutes) is not an error: it returns the original change withduplicate: true.