Workflow RPCs
Writes go through workflow RPCs — intent-named Postgres functions that own the transition logic. They're the same functions the MCP tools wrap, exposed over PostgREST at /rest/v1/rpc/<function>. Every function is SECURITY INVOKER, so RLS and the transition triggers apply to you as the caller.
curl -X POST \
"https://jionfqfmjinkrmzlsghf.supabase.co/rest/v1/rpc/submit_for_review" \
-H "apikey: $CP_PUBLISHABLE_KEY" \
-H "Authorization: Bearer $CP_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"p_publication":"<uuid>"}'
Every mutation returns the updated row, so you don't need a follow-up read.
Planning
| Function | Arguments | Does |
|---|---|---|
resolve_project | p_project | Resolve a project slug or id to its uuid |
create_collection | project, type, name, dates… | New campaign or section |
create_stub | project, collection, title, idea | Publication in stub |
Publications
| Function | Arguments | Transition |
|---|---|---|
update_draft | publication, title/summary/body/notes | writes content; stub → draft when a body is added |
submit_for_review | p_publication | draft → reviewing |
review_publication | publication, verdict, notes | approve → approved; request_changes → draft |
mark_published | p_publication, p_canonical_url | → published (records the Substack URL) |
archive_publication | p_publication | → archived |
start_promoting | p_publication | approved → promoting; returns channels + per-channel constraints |
Promos
| Function | Arguments | Transition |
|---|---|---|
create_promo | publication, channel, body | new promo in draft |
update_promo | promo, body / scheduled_for | edit copy or schedule |
submit_promo_for_review | p_promo | draft → reviewing |
review_promo | promo, verdict, notes | approve / request changes |
publish_promo | p_promo, p_external_url | manual channels → published |
Dashboard
| Function | Arguments | Returns |
|---|---|---|
pipeline_status | p_project (optional) | counts by status, upcoming scheduled_for, stale items |
Error behavior
An invalid transition returns a structured error that names the current status and the allowed next states, so a client can self-correct. For example, calling start_promoting on a draft returns:
invalid publication transition: draft -> promoting (allowed from draft: reviewing, archived)
The MCP tool surface is a thin, schema-documented layer over exactly these RPCs. If you're building an AI client, use MCP; if you're scripting against the database, call the RPCs directly.