{"name":"publica.la website API","description":"The publica.la marketing site's own JSON API: blog posts, the changelog, booking pages and the newsletter. The publishing platform's per-store REST API v3 is a different API, documented at https:\/\/docs.publica.la\/","version":"v1","base_url":"https:\/\/publica.la\/api\/v1","documentation":"https:\/\/publica.la\/en\/developers","openapi":"https:\/\/publica.la\/openapi.json","openapi_yaml":"https:\/\/publica.la\/openapi.yaml","api_catalog":"https:\/\/publica.la\/.well-known\/api-catalog","llms_txt":"https:\/\/publica.la\/llms.txt","platform_api_docs":"https:\/\/docs.publica.la\/","sandbox":{"url":"https:\/\/docs.publica.la\/rest-api-v3\/content\/content-v3-sandbox","description":"A try-it-out page for the publica.la **platform** REST API v3 \u2014 the per-store API, not this one. There is no sandbox for the website API: the anonymous endpoints below are the way to make a real call with no credentials."},"status_page":"https:\/\/status.publica.la\/","contact":{"general":"hello@publica.la","support":"support@publica.la","security":"security@publica.la"},"mcp":{"url":"https:\/\/publica.la\/mcp","manifest":"https:\/\/publica.la\/.well-known\/mcp.json","server_card":"https:\/\/publica.la\/.well-known\/mcp\/server-card.json","transport":"streamable-http","authentication":"none","docs_mcp":"https:\/\/docs.publica.la\/mcp"},"a2a":{"url":"https:\/\/publica.la\/api\/a2a","agent_card":"https:\/\/publica.la\/.well-known\/agent-card.json","protocol_version":"0.3.0","transport":"JSONRPC","authentication":"none","skills":["site-guide"],"description":"An Agent2Agent endpoint with one method, `message\/send`, and one skill, `site-guide`: it answers with the publica.la entry point that answers the question it was sent. Deterministic and anonymous \u2014 no streaming, and no tasks are kept, which is why every capability on the card is false."},"agent_documents":{"index":"https:\/\/publica.la\/index.md","agents":"https:\/\/publica.la\/agents.md","guide":"https:\/\/publica.la\/guide.md","auth":"https:\/\/publica.la\/auth.md","api":"https:\/\/publica.la\/api.md","pricing":"https:\/\/publica.la\/pricing.md","skill":"https:\/\/publica.la\/skills\/publicala\/SKILL.md"},"anonymous_endpoints":[{"method":"GET","path":"\/api\/v1\/site\/posts","name":"site.posts.index","description":"Search published blog posts and product updates. No key required."},{"method":"GET","path":"\/api\/v1\/site\/posts\/{slug}","name":"site.posts.show","description":"Fetch one published post by slug, body included. No key required."},{"method":"GET","path":"\/api\/v1\/site\/changelog","name":"site.changelog","description":"List published changelog entries, newest month first. No key required."},{"method":"GET","path":"\/api\/v1\/site\/pricing","name":"site.pricing","description":"The three publica.la plans with prices and features. No key required."},{"method":"GET","path":"\/api\/v1\/site\/overview","name":"site.overview","description":"What publica.la is, when to use it, what it is not for, and every machine-readable entry point. Start here. No key required."}],"authentication":{"type":"http","scheme":"bearer","header":"Authorization: Bearer rnd_...","how_to_get_a_key":"Keys are issued by the publica.la team \u2014 hello@publica.la","scopes":"Every endpoint below names the scope its key must carry.","challenge":"A 401 carries WWW-Authenticate: Bearer realm=\"publica.la website API\", error=\"invalid_token\", error_description=\"Send Authorization: Bearer <key>\", resource_metadata=\"https:\/\/publica.la\/.well-known\/oauth-protected-resource\"","anonymous_tier":"The \/api\/v1\/site\/* endpoints and the MCP server need no credential at all. Everything else does."},"idempotency":{"header":"Idempotency-Key","replay_header":"Idempotency-Replayed","ttl_seconds":86400,"methods":["POST","PUT","PATCH","DELETE"],"description":"Optional. Send Idempotency-Key on a write and the first answer is replayed for 86400 seconds, with Idempotency-Replayed: true, instead of the write happening twice. The same key with a different body is a 422 with code idempotency_key_reused.","not_remembered":"A 5xx, and any refusal about the caller rather than the request (401, 403, 429): a key that met one of those is still usable, because those are the answers you are meant to fix and retry."},"rate_limits":{"policy":"300 requests per minute per key","requests_per_minute":300,"window_seconds":60,"headers":["RateLimit-Policy","RateLimit","RateLimit-Limit","RateLimit-Remaining","RateLimit-Reset","Retry-After"]},"errors":{"format":"JSON, RFC 9457 members alongside message","docs":"https:\/\/publica.la\/en\/developers#errors"},"endpoints":[{"method":"GET","methods":["GET"],"path":"\/api\/v1\/site\/posts","name":"site.posts.index","auth":"none","scope":null,"description":"Search published blog posts and product updates. No key required."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/site\/posts\/{slug}","name":"site.posts.show","auth":"none","scope":null,"description":"Fetch one published post by slug, body included. No key required."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/site\/changelog","name":"site.changelog","auth":"none","scope":null,"description":"List published changelog entries, newest month first. No key required."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/site\/pricing","name":"site.pricing","auth":"none","scope":null,"description":"The three publica.la plans with prices and features. No key required."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/site\/overview","name":"site.overview","auth":"none","scope":null,"description":"What publica.la is, when to use it, what it is not for, and every machine-readable entry point. Start here. No key required."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/posts","name":"posts.index","auth":"bearer","scope":"content.read","description":"List blog posts, newest first."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/posts\/{post}","name":"posts.show","auth":"bearer","scope":"content.read","description":"Fetch one blog post by id or slug."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/posts","name":"posts.store","auth":"bearer","scope":"content.write","description":"Create a blog post as a draft."},{"method":"PUT","methods":["PUT","PATCH"],"path":"\/api\/v1\/posts\/{post}","name":"posts.update","auth":"bearer","scope":"content.write","description":"Update a blog post, including its per-locale fields."},{"method":"DELETE","methods":["DELETE"],"path":"\/api\/v1\/posts\/{post}","name":"posts.destroy","auth":"bearer","scope":"content.write","description":"Delete a blog post."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/posts\/{post}\/publish","name":"posts.publish","auth":"bearer","scope":"content.write","description":"Publish a blog post."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/posts\/{post}\/cover-image","name":"posts.cover-image","auth":"bearer","scope":"content.write","description":"Upload the cover image for a blog post."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/posts\/{post}\/slack-preview","name":"posts.slack-preview","auth":"bearer","scope":"content.write","description":"Post a review preview of a blog post to Slack."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/event-types","name":"event-types.index","auth":"bearer","scope":"scheduling.read","description":"List booking pages; ?kind=personal|catalogue narrows it."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/event-types\/{eventType}","name":"event-types.show","auth":"bearer","scope":"scheduling.read","description":"Fetch one booking page."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/event-types","name":"event-types.store","auth":"bearer","scope":"scheduling.write","description":"Create a booking page."},{"method":"PUT","methods":["PUT","PATCH"],"path":"\/api\/v1\/event-types\/{eventType}","name":"event-types.update","auth":"bearer","scope":"scheduling.write","description":"Update a booking page."},{"method":"DELETE","methods":["DELETE"],"path":"\/api\/v1\/event-types\/{eventType}","name":"event-types.destroy","auth":"bearer","scope":"scheduling.write","description":"Delete a booking page."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/newsletter\/stats","name":"newsletter.stats","auth":"bearer","scope":"newsletter.read","description":"Read the sendable audience and per-edition engagement counters."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/newsletter-campaigns","name":"newsletter-campaigns.index","auth":"bearer","scope":"newsletter.read","description":"List newsletter editions."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/newsletter-campaigns\/{newsletterCampaign}","name":"newsletter-campaigns.show","auth":"bearer","scope":"newsletter.read","description":"Fetch one newsletter edition."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/newsletter-campaigns","name":"newsletter-campaigns.store","auth":"bearer","scope":"newsletter.write","description":"Create a newsletter edition."},{"method":"PUT","methods":["PUT","PATCH"],"path":"\/api\/v1\/newsletter-campaigns\/{newsletterCampaign}","name":"newsletter-campaigns.update","auth":"bearer","scope":"newsletter.write","description":"Update a newsletter edition."},{"method":"DELETE","methods":["DELETE"],"path":"\/api\/v1\/newsletter-campaigns\/{newsletterCampaign}","name":"newsletter-campaigns.destroy","auth":"bearer","scope":"newsletter.write","description":"Delete a newsletter edition."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/newsletter-campaigns\/{newsletterCampaign}\/send-test","name":"newsletter-campaigns.send-test","auth":"bearer","scope":"newsletter.write","description":"Send one test copy of an edition."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/newsletter-assets","name":"newsletter-assets.store","auth":"bearer","scope":"newsletter.write","description":"Upload an image for a newsletter edition and get its public URL."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/newsletter-campaigns\/{newsletterCampaign}\/send","name":"newsletter-campaigns.send","auth":"bearer","scope":"newsletter.send","description":"Fire an edition at the list. Irreversible, and throttled to 10 calls a minute."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/subscribers","name":"subscribers.store","auth":"bearer","scope":"subscribers.write","description":"Add one newsletter subscriber."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/subscribers\/origami","name":"subscribers.origami","auth":"bearer","scope":"subscribers.write","description":"Register an Origami sign-up as a subscriber."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/subscribers\/bulk","name":"subscribers.bulk","auth":"bearer","scope":"subscribers.write","description":"Add subscribers in bulk. Throttled to 60 calls a minute."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/suppressions\/bulk","name":"suppressions.bulk","auth":"bearer","scope":"suppressions.write","description":"Suppress addresses in bulk. Irreversible in practice, and throttled to 60 calls a minute."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/releases","name":"releases.index","auth":"bearer","scope":"content.read","description":"Deprecated alias of posts.index; kept for existing consumers."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/releases\/{post}","name":"releases.show","auth":"bearer","scope":"content.read","description":"Deprecated alias of posts.show."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/releases","name":"releases.store","auth":"bearer","scope":"content.write","description":"Deprecated alias of posts.store."},{"method":"PUT","methods":["PUT","PATCH"],"path":"\/api\/v1\/releases\/{post}","name":"releases.update","auth":"bearer","scope":"content.write","description":"Deprecated alias of posts.update."},{"method":"DELETE","methods":["DELETE"],"path":"\/api\/v1\/releases\/{post}","name":"releases.destroy","auth":"bearer","scope":"content.write","description":"Deprecated alias of posts.destroy."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/releases\/{post}\/publish","name":"releases.publish","auth":"bearer","scope":"content.write","description":"Deprecated alias of posts.publish."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/releases\/{post}\/slack-preview","name":"releases.slack-preview","auth":"bearer","scope":"content.write","description":"Deprecated alias of posts.slack-preview."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/changelog","name":"changelog.index","auth":"bearer","scope":"content.read","description":"List changelog entries."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/changelog\/{changelogEntry}","name":"changelog.show","auth":"bearer","scope":"content.read","description":"Fetch one changelog entry."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/changelog","name":"changelog.store","auth":"bearer","scope":"content.write","description":"Create a changelog entry."},{"method":"PUT","methods":["PUT","PATCH"],"path":"\/api\/v1\/changelog\/{changelogEntry}","name":"changelog.update","auth":"bearer","scope":"content.write","description":"Update a changelog entry."},{"method":"DELETE","methods":["DELETE"],"path":"\/api\/v1\/changelog\/{changelogEntry}","name":"changelog.destroy","auth":"bearer","scope":"content.write","description":"Delete a changelog entry."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/changelog\/{changelogEntry}\/publish","name":"changelog.publish","auth":"bearer","scope":"content.write","description":"Publish a changelog entry."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/changelog\/{changelogEntry}\/slack-preview","name":"changelog.slack-preview","auth":"bearer","scope":"content.write","description":"Post a review preview of a changelog entry to Slack."},{"method":"GET","methods":["GET"],"path":"\/api\/v1\/widget\/status","name":"generated::mw9I9khqOnpU60aY","auth":"widget-hmac","scope":null,"description":"The farfalla notification widget. Gated by an HMAC token and an origin allow-list rather than a bearer key."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/widget\/seen","name":"generated::7lGzShksSa0rNlm7","auth":"widget-hmac","scope":null,"description":"The farfalla notification widget. Gated by an HMAC token and an origin allow-list rather than a bearer key."},{"method":"POST","methods":["POST"],"path":"\/api\/v1\/widget\/seen-all","name":"generated::Y2qJRv3XHSCeO8kX","auth":"widget-hmac","scope":null,"description":"The farfalla notification widget. Gated by an HMAC token and an origin allow-list rather than a bearer key."}]}