S2P
S2P documentation

Operate release marketing from GitHub to approved posts.

Ship 2 Post turns engineering release signals into branded, channel-ready content with approval control, API access, webhooks, billing gates, and auditability for production teams.

Source

GitHub

Generation

AI drafts

Delivery

Social + API

Quickstart

Connect a workspace, generate drafts, then use the API where automation needs to leave the browser.

Most teams begin in the webapp and add the API after the release workflow is stable.

  1. 1Create or select a workspace.
  2. 2Install the GitHub App from Repositories.
  3. 3Create a brand profile and channel templates.
  4. 4Create a trigger rule for release events.
  5. 5Review drafts, approve posts, and connect API consumers as needed.

Workspace API smoke test

# 1. Create an API key in S2P
# Settings -> API keys -> Create key

# 2. Read workspace state from the Convex HTTP API
curl https://<your-convex-site>/v1/workspace \
  -H "Authorization: Bearer s2p_<token>"

# 3. List drafts ready for approval
curl 'https://<your-convex-site>/v1/drafts?status=ready' \
  -H "Authorization: Bearer s2p_<token>"

Core concepts

The domain model is intentionally small.

Everything belongs to a workspace. Repository signals become drafts through trigger rules, and only approved content becomes a post.

Workspace

The billing, membership, repository, API key, and publishing boundary.

Repository

A GitHub source watched for releases, tags, pull requests, and qualifying changes.

Brand profile

The company description, audience, voice, phrases, and compliance rules used by AI generation.

Channel template

A platform-specific content shape: length, structure, hashtags, links, and image behavior.

Trigger rule

Automation logic that decides when release signals should become draft posts.

Draft variant

One generated post candidate for one platform before approval or publishing.

How the webapp works

The webapp is the control plane for release automation.

Use it to connect sources, decide what should generate, edit output, approve publishing, and keep operational visibility in one place.

01

Connect GitHub

Install the S2P GitHub App, select repositories, and let release signals flow into the workspace.

02

Define brand and channels

Create brand profiles, voice rules, channel templates, and platform-specific constraints.

03

Create trigger rules

Choose which releases, tags, pull requests, or changelog updates should generate drafts.

04

Review generated drafts

S2P prepares channel-native variants, optional images, scores, and publishing metadata.

05

Approve and publish

Approve manually or use autonomous rules on eligible plans, then publish to connected destinations.

06

Measure and audit

Inspect posts, metrics, logs, and admin-only audit records for operational traceability.

Webapp pages

Every major page has one operational owner in the workflow.

This is the current implemented app surface: what each page is for, what it controls, and which pages are restricted by role, plan, or S2P-admin status.

Sources and automation

Repositories and trigger rules decide which GitHub events become release marketing work.

Content operations

Drafts, draft details, posts, and post details cover review, edit, approval, and publication state.

Reporting

Analytics and metrics endpoints expose performance where the plan includes analytics.

Workspace configuration

Settings covers identity, billing, team access, and AI model selection.

Billing gates

Plan and checkout surfaces control entitlements such as API access, image posts, and team members.

Admin observability

Logs and audit views are visible only to S2P admins with the backend boolean set to true.

PageRouteWhat it controls
Dashboard/dashboardWorkspace overview, recent activity, setup progress, and operational shortcuts.
Repositories/reposGitHub App installation, repository inventory, ingestion health, repository removal, and repository plan limits.
Repository detail/repos/:repoIdRepository-specific release signals, trigger context, connected state, and cleanup actions.
Brands/brandsBrand profile creation, voice setup, positioning, do-use phrases, do-not-use phrases, and compliance rules.
Brand detail/brands/:brandIdBrand profile editing and channel templates for platform-specific content structure.
Connections/connectionsSocial OAuth starts, manual credentials, Bluesky app-password flow, refresh, disconnect, and custom webhook destinations.
Trigger rules/triggersAutomation rules, active/inactive state, signal filters, brand selection, and channels.
New trigger rule/triggers/newRule creation, platform selection, and required channel-template preparation.
Trigger rule detail/triggers/:ruleIdRule edits, activation toggles, approval-mode changes, channel changes, and rule deletion.
Drafts/draftsGenerated draft queue, status filtering, approval, rejection, regeneration, archive, and bulk actions.
Draft detail/drafts/:draftIdVariant review, body editing, approval decisions, image assets, citations, scores, and publish actions.
Posts/postsPublished and scheduled post inventory, status filters, channels, and delivery state.
Post detail/posts/:postIdPost payload, destination, external URL, delivery metadata, and performance context.
Analytics/analyticsWorkspace metrics, post analytics, channel performance, metric pulls, and export-gated reporting.
Archive/archiveArchived drafts, posts, repositories, rules, and restore or hard-delete flows where supported.
API keys/api-keysOwner-only API key creation, scope selection, one-time plaintext display, revocation, and deletion of revoked keys.
Settings/settingsWorkspace identity, AI model selection, plan and billing, and team access control.
Logs/logsS2P-admin-only operational logs for backend review.
Audit/auditS2P-admin-only audit log review with resource, actor, action, and timestamp context.
Account/accountUser account preferences and account-level navigation.
Archived workspaces/workspaces/archivedWorkspace restore and permanent deletion flows for archived workspaces.

Workspace bootstrap

On first authenticated use, S2P provisions a personal workspace when the user has no active membership.

Workspace selection

The selected workspace is stored locally and reconciled against the live membership list.

Billing gates

Locked features show upgrade dialogs in the UI and are also enforced in Convex mutations/actions.

GitHub ingestion

GitHub App webhooks create normalized release signals that trigger active matching rules.

AI pipeline

Draft generation gathers repository, signal, brand, voice, channel, recent draft, and billing context before calling OpenRouter.

Approval

Free workspaces require review before publishing. Eligible paid workspaces can use autonomous publishing.

Publishing

Approved variants publish to connected social destinations or custom webhooks when platform and plan rules allow it.

Auditability

Mutations and publishing operations write audit rows; visibility is restricted to S2P admins for logs and audit pages.

Archive and restore

Archive screens preserve recoverability before permanent deletion flows are allowed.

Membership and access

Member actions are role-gated and team-member features require the matching plan entitlement.

AI generation

S2P generates structured drafts, not one-off chat output.

The pipeline gathers release context, builds a release brief, creates channel variants, rewrites for brand voice, scores quality, and optionally generates image assets for eligible workspaces.

Release brief

The pipeline normalizes repository context into a concise angle, audience hook, customer value, and key points.

Channel variants

Templates control platform, length, structure, link behavior, hashtag ranges, and image requirements.

Model selection

Starter workspaces can choose premium text models. Growth workspaces can also choose image models.

Publishing destinations

Publishing starts only after the workspace is allowed to use the requested channel.

The billing and entitlement guard runs before drafts are generated and again before publishing operations that need paid features.

Connected social platforms

OAuth and credential-based destinations are managed in Connections. S2P stores publishing tokens server-side.

Custom webhooks

Use custom webhook channels when approved posts should go to a CMS, community bridge, static site builder, or internal system.

API authentication

Every public API request uses a workspace API key.

Create API keys from the app. Plaintext keys are shown once, stored only as hashes, and must be sent as bearer tokens.

  • Header format: Authorization: Bearer s2p_<token>.
  • API access is a Growth entitlement.
  • Owner-level workspace permission is required to create keys.
  • Keys are scoped to one workspace and can be revoked.

Authentication header

Authorization: Bearer s2p_<token>

API reference

The v1 API exposes workspace operations for production integrations.

The v1 API is designed as the programmatic equivalent of the logged-in workspace UI. Use collection endpoints for lists and action endpoints for setup, settings, approval, publishing, archive, analytics, billing, and access-control operations.

Base URL

Use your deployed Convex HTTP Actions URL, then append /v1/...

Authentication

Send Authorization: Bearer s2p_<token> on every /v1 request.

JSON

Requests and responses are JSON unless a future endpoint states otherwise.

IDs

IDs are Convex document IDs. Invalid ids return validation_failed instead of leaking validator traces.

Pagination

List endpoints use limit and cursor where available, returning has_more and next_cursor.

Errors

Errors use { error, code, details? }. Common codes include validation_failed, forbidden, plan_required, not_found, and method_not_allowed.

Permissions

API scope, creator role, workspace membership, S2P admin status, and plan entitlement can all be checked.

ResourceMethodsPrimary path
AccountGET, PATCH/v1/account
WorkspaceGET, PATCH/v1/workspace
Workspace settingsGET, PATCH actions/v1/workspace/settings
WorkspacesGET, POST actions/v1/workspaces
BillingGET, POST actions/v1/billing
API keysGET, POST/v1/api-keys
RepositoriesGET, POST actions/v1/repositories
Release signalsGET/v1/release-signals
Trigger rulesGET, POST, PATCH, DELETE/v1/trigger-rules
Brand profilesGET, POST, PATCH, DELETE/v1/brand-profiles
Channel templatesGET, POST, PATCH, DELETE/v1/channel-templates
Social connectionsGET, POST actions/v1/social-connections
DraftsGET, POST actions/v1/drafts
PostsGET/v1/posts
MembersGET, POST, PATCH/v1/members
MetricsGET/v1/metrics
AnalyticsGET/v1/analytics
ArchiveGET, POST actions/v1/archive
OnboardingGET/v1/onboarding/progress
Admin logsGET/v1/logs

Response contract

{ "data": { "items": [] }, "meta": { "has_more": false, "next_cursor": null } }
{ "error": "Human readable message.", "code": "machine_readable_code" }

API workflows

These workflows mirror what operators can do in the webapp.

Use this section when you need to automate the same actions that are available through the logged-in product surface.

First workspace setup

Create/list workspaces, read onboarding progress, start GitHub install, connect social destination, then edit the seeded brand profile and trigger rule.

/v1/workspaces, /v1/onboarding/progress, /v1/github/install/begin, /v1/social-connections/*, /v1/brand-profiles, /v1/trigger-rules

Workspace settings

Read resolved settings, update text/image models, and configure draft aggregation cadence with plan gates enforced. S2P branding lives in the in-app settings tab.

/v1/workspace/settings, /v1/workspace/settings/ai-models, /v1/workspace/settings/draft-aggregation

Draft review and aggregation

List ready drafts, aggregate multiple drafts into one, edit variants, approve or reject, then publish approved variants.

/v1/drafts, /v1/drafts/aggregate, /v1/draft-variants, /v1/drafts/approve, /v1/drafts/reject, /v1/drafts/publish

Analytics and operations

Read metrics, dashboard KPIs, analytics breakdowns, archive items, restore or hard-delete archived items, and inspect S2P-admin audit/log data.

/v1/metrics, /v1/analytics/*, /v1/archive, /v1/archive/restore, /v1/archive/delete, /v1/audit-logs, /v1/logs

Billing and access control

Read plan state, create checkout or billing portal sessions, invite members, update roles, revoke access, and manage API keys.

/v1/billing, /v1/billing/checkout, /v1/billing/portal, /v1/members, /v1/members/update-role, /v1/api-keys

Settings and model selection

# Read resolved settings and available model options
curl https://<your-convex-site>/v1/workspace/settings \
  -H "Authorization: Bearer s2p_<token>"

# Update text and image model settings
curl -X PATCH https://<your-convex-site>/v1/workspace/settings/ai-models \
  -H "Authorization: Bearer s2p_<token>" \
  -H "Content-Type: application/json" \
  -d '{"text_model":"~openai/gpt-mini-latest","image_model":"google/gemini-3-pro-image-preview"}'

# Configure aggregation cadence
curl -X PATCH https://<your-convex-site>/v1/workspace/settings/draft-aggregation \
  -H "Authorization: Bearer s2p_<token>" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true,"max_posts_per_window":1,"window_days":1,"auto_archive_source_drafts":true}'

Draft aggregation and publishing

# Aggregate multiple ready drafts into one post-ready draft
curl -X POST https://<your-convex-site>/v1/drafts/aggregate \
  -H "Authorization: Bearer s2p_<token>" \
  -H "Content-Type: application/json" \
  -d '{"draft_ids":["draftId1","draftId2"],"archive_source_drafts":true}'

# Approve the aggregate draft
curl -X POST 'https://<your-convex-site>/v1/drafts/approve?id=<draftId>' \
  -H "Authorization: Bearer s2p_<token>"

# Publish approved variants
curl -X POST 'https://<your-convex-site>/v1/drafts/publish?id=<draftId>' \
  -H "Authorization: Bearer s2p_<token>"

Analytics and archive operations

# Read UI-equivalent analytics panels
curl https://<your-convex-site>/v1/analytics/dashboard?period=day \
  -H "Authorization: Bearer s2p_<token>"

# Archive selected items
curl -X POST https://<your-convex-site>/v1/archive \
  -H "Authorization: Bearer s2p_<token>" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"kind":"draft","id":"<draftId>"}]}'

# Restore selected archived items
curl -X POST https://<your-convex-site>/v1/archive/restore \
  -H "Authorization: Bearer s2p_<token>" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"kind":"draft","id":"<draftId>"}]}'
OperationPathRequest bodyNotes
Update accountPATCH /v1/account{ email?, name?, avatar_url? }Updates the API-key creator profile.
Create workspacePOST /v1/workspaces{ "name": "Workspace name" }Seeds starter brand, channel template, and trigger rule.
Update AI modelsPATCH /v1/workspace/settings/ai-models{ text_model?, image_model? }Text model selection requires premium AI. Image model selection requires image posts.
Update draft aggregation settingsPATCH /v1/workspace/settings/draft-aggregation{ enabled, max_posts_per_window, window_days, auto_archive_source_drafts }Requires draft aggregation entitlement.
Create checkout sessionPOST /v1/billing/checkout{ plan_slug, billing_cycle, return_path? }Owner only. plan_slug is starter, growth, scale, or business.
Begin OAuth connectionPOST /v1/social-connections/oauth/begin{ platform, redirect_after? }Returns an auth_url for browser completion.
Connect BlueskyPOST /v1/social-connections/bluesky{ handle, app_password }Credential-based connection without OAuth redirect.
Connect MastodonPOST /v1/social-connections/mastodon{ instance_url, access_token }Verifies credentials against the Mastodon instance.
Connect webhook destinationPOST /v1/social-connections/webhook{ platform, webhook_url, label?, signing_secret? }Supports discord, slack, hacker_news, substack, and custom_webhook.
Bulk draft actionPOST /v1/drafts/bulk{ action, ids | draft_ids }action is approve or reject. Archive drafts through /v1/archive.
Aggregate draftsPOST /v1/drafts/aggregate{ draft_ids, archive_source_drafts? }Requires at least two ready drafts and draft aggregation entitlement.
Publish draftPOST /v1/drafts/publish?id={ channelId? }Schedules publish jobs for variants with active matching connections.
Archive, restore, or hard-delete itemsPOST /v1/archive, POST /v1/archive/restore, POST /v1/archive/delete{ "items": [{ "kind": "draft", "id": "..." }] }Kinds include brand_profile, repository, trigger_rule, post, draft, job_run, and audit_log. job_run and audit_log require S2P admin access.
Invite memberPOST /v1/members{ email, role }Requires team member entitlement and member invite permission.
Update member rolePATCH /v1/members/update-role?id={ role }Uses membership id in the query string.
Create API keyPOST /v1/api-keys{ name, scopes }Plaintext key is returned once.

Endpoint catalog

Every implemented public v1 HTTP route is listed here.

Paths are relative to your deployed Convex HTTP Actions URL. Query parameters shown with ?id= or ?postId= are required unless noted otherwise.

MethodPathScopePurpose and gates
GET/v1/workspaceworkspace:readRead current API-key workspace metadata, plan, and status.
PATCH, POST/v1/workspaceworkspace:writeUpdate workspace name or slug. Structured settings use /v1/workspace/settings/*.
GET, PATCH, POST/v1/accountaccount:read/writeRead or update the API-key creator account profile.
GET/v1/workspace/settingssettings:readRead resolved AI model, draft aggregation, branding, plan access, options, and presets.
PATCH, POST/v1/workspace/settings/ai-modelssettings:writeUpdate text and image AI models with the same tier checks as the UI.
PATCH, POST/v1/workspace/settings/draft-aggregationsettings:writeUpdate draft aggregation cadence and source-draft archive behavior.
GET, POST/v1/workspacesworkspaces:read/writeList account workspaces or create a new workspace with starter brand and trigger templates.
GET/v1/workspaces/get?id=workspaces:readGet an account workspace by id.
POST/v1/workspaces/archive?id=workspaces:writeArchive a workspace. Owner only.
POST/v1/workspaces/restore?id=workspaces:writeRestore an archived workspace. Owner only.
DELETE, POST/v1/workspaces/delete?id=workspaces:writePermanently delete an archived workspace and scoped data. Owner only.
GET/v1/billingbilling:readRead billing catalog, current plan, subscription, and workspace billing state.
POST/v1/billing/checkoutbilling:writeCreate Stripe checkout or subscription update portal session. Owner only.
POST/v1/billing/portalbilling:writeCreate a Stripe billing portal session. Owner only.
GET/v1/api-keysapi_keys:readList API keys. Requires API key read permission.
POST/v1/api-keysapi_keys:writeCreate API key. Requires Growth API access and api_key create permission.
POST/v1/api-keys/revoke?id=api_keys:writeRevoke an API key by id.
DELETE, POST/v1/api-keys/delete?id=api_keys:writeDelete a revoked API key by id.
GET/v1/repositoriesrepositories:readList repositories. Supports status, limit, and cursor.
GET/v1/repositories/get?id=repositories:readGet one repository by id.
GET/v1/repositories/statsrepositories:readRead per-repository trigger counts and recent signal counts.
GET/v1/release-signalsrepositories:readList release signals by kind, repo_id, and limit.
GET/v1/release-signals/get?id=repositories:readGet one release signal by id.
POST/v1/github/install/beginrepositories:writeStart GitHub App installation for the workspace.
DELETE, POST/v1/repositories/remove?id=repositories:writeRemove a connected repository by id.
GET/v1/brand-profilesbrand_profiles:readList brand profiles with pagination.
POST/v1/brand-profilesbrand_profiles:writeCreate a brand profile and required voice context.
PATCH, POST/v1/brand-profiles?id=brand_profiles:writeUpdate a brand profile by id.
DELETE, POST/v1/brand-profiles/delete?id=brand_profiles:writeDelete a brand profile by id.
GET/v1/brand-profiles/get?id=brand_profiles:readGet one brand profile by id.
GET/v1/channel-templates?brandProfileId=brand_profiles:readList channel templates for a brand profile.
POST/v1/channel-templatesbrand_profiles:writeAdd a channel template to a brand profile.
PATCH, POST/v1/channel-templates?id=brand_profiles:writeUpdate a channel template by id.
DELETE, POST/v1/channel-templates/delete?id=brand_profiles:writeDelete a channel template by id.
GET/v1/channel-templates/get?id=brand_profiles:readGet one channel template by id.
GET/v1/social-connectionssocial_connections:readList connected publishing destinations.
POST/v1/social-connections/oauth/beginsocial_connections:writeBegin OAuth for supported social platforms.
POST/v1/social-connections/blueskysocial_connections:writeConnect Bluesky with app-password credentials.
POST/v1/social-connections/mastodonsocial_connections:writeConnect Mastodon with instance URL and access token.
POST/v1/social-connections/webhooksocial_connections:writeConnect Discord, Slack, Hacker News, Substack, or a custom webhook destination.
POST/v1/social-connections/test?id=social_connections:writePublish a test post through one active social connection.
POST/v1/social-connections/refresh?id=social_connections:writeRefresh one social connection by id.
POST/v1/social-connections/disconnect?id=social_connections:writeDisconnect one social connection by id.
GET/v1/trigger-rulestrigger_rules:readList trigger rules with pagination.
POST/v1/trigger-rulestrigger_rules:writeCreate a trigger rule with brand and channel template references.
GET/v1/trigger-rules/get?id=trigger_rules:readGet one trigger rule by id.
PATCH, POST/v1/trigger-rules?id=trigger_rules:writeUpdate one trigger rule by id.
POST/v1/trigger-rules/toggle?id=trigger_rules:writeToggle active state for a trigger rule.
DELETE, POST/v1/trigger-rules/delete?id=trigger_rules:writeDelete one trigger rule by id.
GET/v1/draftsdrafts:readList drafts. Supports status, signalId, limit, and cursor.
GET/v1/drafts/get?id=drafts:readGet one draft and its variants by id.
POST/v1/drafts/approve?id=drafts:writeApprove a draft and queue publishing when applicable.
POST/v1/drafts/reject?id=drafts:writeReject a draft by id.
POST/v1/drafts/regenerate?id=drafts:writeRequest draft regeneration by id.
POST/v1/drafts/bulkdrafts:writeBulk approve, reject, or archive draft ids.
POST/v1/drafts/aggregatedrafts:writeAggregate multiple ready drafts into one ready draft. Requires draft aggregation entitlement.
POST/v1/drafts/publish?id=drafts:write + posts:writePublish an approved draft to selected channel templates.
PATCH, POST/v1/draft-variants?id=drafts:writeUpdate one draft variant body or metadata by id.
POST/v1/draft-variants/update?id=drafts:writeCompatibility route for variant updates.
GET/v1/postsposts:readList posts. Supports status, channel, limit, and cursor.
GET/v1/posts/get?id=posts:readGet one post by id.
GET/v1/membersmembers:readList workspace members with pagination.
POST/v1/membersmembers:writeInvite a member. Requires team_members plan entitlement.
PATCH, POST/v1/members/update-role?id=members:writeUpdate member role by membership id.
POST/v1/members/revoke?id=members:writeRevoke a membership by id.
GET/v1/audit-logsaudit_logs:readS2P admin only. Supports limit, cursor, since, until, actor_user_id, action, and resource_kind.
GET/v1/audit-logs/get?id=audit_logs:readS2P admin only. Get one visible audit log by id.
GET/v1/metricsmetrics:readRead workspace analytics. Requires post_analytics.
GET/v1/metrics/post?postId=metrics:readRead metrics for one post. Requires post_analytics.
GET/v1/metrics/exportmetrics:exportExport analytics. Requires analytics export plus analytics entitlement.
GET/v1/analytics/dashboardanalytics:readRead dashboard KPI rollup and sparkline data.
GET/v1/analytics/top-postsanalytics:readRead top posts by engagement for the analytics page.
GET/v1/analytics/platform-breakdownanalytics:readRead published post and metric totals grouped by platform.
GET/v1/analytics/draft-funnelanalytics:readRead generated, ready, approved, and published draft funnel counts.
GET, POST/v1/archivearchive:read/writeList archived items or archive selected items.
POST/v1/archive/restorearchive:writeRestore selected archived items.
DELETE, POST/v1/archive/deletearchive:writePermanently delete selected archived items.
GET/v1/onboarding/progressonboarding:readRead first-steps progress for repo, social, brand, and trigger setup.
GET/v1/logslogs:readS2P admin only. Read job run logs for the logs page.
POST/v1/test/simulate-releasetest:writeDevelopment smoke-test endpoint. Do not enable in production deployments.
POST/v1/test/cleanuptest:writeDevelopment cleanup endpoint. Do not enable in production deployments.

Scopes and permissions

A request must pass scope, role, membership, S2P-admin, and plan checks where applicable.

The token alone is not the whole authorization model. API handlers combine API key scopes with the key creator's current workspace membership and billing entitlement.

Authorization order

  1. 1Validate Authorization: Bearer s2p_<token>.
  2. 2Find API key by prefix and compare the stored hash.
  3. 3Reject revoked keys.
  4. 4Check the required API scope.
  5. 5Check the key creator still has an active workspace role with the required RBAC permission.
  6. 6Check S2P-admin status for audit-log endpoints.
  7. 7Check plan entitlement for gated operations such as API access, team members, analytics, and exports.
ScopeAccess
*Full API access for the workspace.
account:read/writeRead or update the API-key creator profile.
workspace:read/writeRead or update current workspace metadata.
workspaces:read/writeList, create, archive, restore, and permanently delete account workspaces.
settings:read/writeRead or update AI models, draft aggregation, and S2P branding settings.
billing:read/writeRead billing state and create checkout or billing portal sessions.
repositories:read/writeList repositories, inspect release signals, begin GitHub installs, and remove repositories.
brand_profiles:read/writeManage brand profiles and channel templates.
social_connections:read/writeList, connect, refresh, and disconnect publishing destinations.
trigger_rules:read/writeList, create, update, toggle, and delete automation rules.
drafts:read/writeList drafts, get variants, approve, reject, regenerate, bulk action, and edit variants.
posts:read/writeRead posts and publish approved drafts where the endpoint requires post write access.
members:read/writeList members, invite teammates, update roles, and revoke access.
audit_logs:readRead audit logs. Also requires the API key creator to be an S2P admin.
metrics:read/exportRead analytics or export metrics when the plan includes those entitlements.
analytics:read/exportRead UI analytics models and analytics exports when plan entitlements allow them.
archive:read/writeList archive, archive items, restore items, and hard-delete items.
onboarding:readRead first-steps onboarding completion state.
logs:readRead job run logs. Also requires the API key creator to be an S2P admin.
api_keys:read/writeManage API keys through the API. Requires API key RBAC permissions.
test:writeDevelopment-only smoke-test and cleanup endpoints.

Outbound webhooks

Webhook receivers should be fast, idempotent, and tolerant of retries.

Return any 2xx status for success. Use the idempotency key to avoid duplicate downstream publishing.

Example delivery headers

Content-Type: application/json
User-Agent: Ship2Post/1.0
X-Ship2Post-Platform: custom_webhook
X-Ship2Post-Idempotency-Key: post:123:custom_webhook
Authorization: Bearer <optional secret>

Receiver checklist

  • Validate the optional bearer secret when configured.
  • Persist the idempotency key before publishing externally.
  • Queue slow work and answer quickly.
  • Return a public URL when your destination creates one.

Security model

Workspace boundaries, roles, and server-side secrets are the security baseline.

The browser never receives provider secrets. API keys, social tokens, GitHub secrets, and AI provider keys stay server-side.

RBAC

Owners, admins, editors, and viewers have different access to workspace, billing, member, API key, and publishing operations.

Key storage

API keys are generated once, hashed, prefixed for lookup, and never stored as plaintext.

Auditability

Workspace mutations, publishing actions, and admin-only logs keep operational review possible.

Billing and limits

Plan entitlements are enforced in the UI and backend.

The API and webapp share the same entitlement model, so locked features cannot be bypassed by calling Convex mutations directly.

Starter

Premium Text AI starts on Starter. Free workspaces use the fixed free text model.

Growth

API access, team members, release links, AI image posts, and image model selection begin on Growth.

Troubleshooting

Most setup issues resolve by checking source, entitlement, and credential state.

Use this sequence before debugging generated content quality or publishing delivery.

Confirm the selected workspace is active and on the expected plan.

Confirm the GitHub App is installed on the target repository.

Confirm the trigger rule is active and points at a brand profile plus channel templates.

Confirm each channel is available on the workspace plan.

Confirm connected social accounts have valid credentials.

Check logs and S2P admin audit views for backend failures.