Skip to content

Webhooks & API

Agents use MCP. Everything else is a small set of HTTP endpoints.

Endpoints

EndpointAuthPurpose
POST GET DELETE /api/mcpAgent key or OAuth access token (Bearer)MCP Streamable HTTP endpoint for agents. 300 requests per minute per agent.
POST /api/webhooks/{siteId}Site webhook tokenReceives CMS change events and WordPress plugin events.
GET /api/w/{workspace}/audit/exportSigned-in admin or ownerFull audit log as JSON, with the integrity check result.
GET /api/healthNoneReturns {"ok":true} when the app and database are reachable, 503 otherwise.
GET /api/cron/schedulesBearer CRON_SECRETRuns 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/agentsBearer CRON_SECRETSends “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/mcpNoneOAuth protected-resource metadata (RFC 9728).
GET /.well-known/oauth-authorization-serverNoneOAuth authorization-server metadata (RFC 8414).
POST /oauth/registerNoneDynamic client registration (RFC 7591).
GET /oauth/authorizeSigned-in userConsent screen: choose workspace and trust level. PKCE S256 required.
POST /oauth/tokenClient (PKCE or secret)Exchange a code or refresh token. Refresh tokens rotate; reuse is detected.
POST /oauth/revokeClientToken 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 token query parameter or the x-lyntcast-token header (x-gatehouse-token is also accepted). Wrong or missing tokens get 401.
  • Bodies must be JSON, up to 1 MB (413 above that, 400 for invalid JSON).
  • Lyntcast recognises the native payloads of each CMS and extracts the document ID:
CMSPayload Lyntcast reads
Sanity_id (drafts are mapped to the published ID), operation from the sanity-operation header
Contentfulsys.id, event from x-contentful-topic
WordPresspost_id / ID / id and post_type, or plugin events
Ghostpost.current.id or page.current.id
Strapimodel and entry.documentId
Webflowpayload.collectionId and payload.id
ShopifyProduct 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, WooCommerce wc-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

  • 401 with a WWW-Authenticate: Bearer resource_metadata=… header when credentials are missing or invalid. OAuth-capable clients use it to start sign-in.
  • 429 with Retry-After: 60 when 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 (same idempotency_key, or an identical proposal within 10 minutes) is not an error: it returns the original change with duplicate: true.