Skip to main content

Base URL

https://api.supapost.so
For local development:
http://localhost:8787

Authentication

All API requests (except public OAuth callbacks and webhooks) require an Authorization header:
Authorization: Bearer YOUR_API_KEY
Supapost supports two credential types — Unkey API keys (prefixed sp_live_...) for server-to-server use and Supabase JWTs issued to browser sessions. See Authentication for details.

Response format

Every response uses a consistent JSON shape. Success — the data directly (or a domain-specific envelope):
{ "id": "abc", "name": "Morning routine" }
Error — always success: false plus a human-readable message:
{ "success": false, "message": "name is required" }

Pagination

Paginated list endpoints use a Stripe-style contract:
{
  "object": "list",
  "data": [],
  "has_more": false,
  "url": "/products"
}
Common query params:
  • limit: number of records to return, default 15, max 100
  • starting_after: fetch the next page after the given object ID
  • ending_before: fetch the previous page before the given object ID
Currently documented paginated list endpoints include /assets, /products, /team/members, and /invites.

Status codes

CodeMeaning
200Success
202Accepted — async job queued, poll /jobs/:id for result
400Bad request — the message field explains what
401Missing or invalid credentials
403Authenticated but not authorized for this resource
404Not found
429Rate limit exceeded — see Retry-After header
500Internal server error
502Upstream provider error (FAL, Higgsfield, TikTok, etc.)

Rate limits

Limits are per-team, bucketed by endpoint tier:
TierLimitEndpoints
Expensive30 / minute/generate/slides, /generate/image, /render, /stores/:id/sync
Mutating120 / minuteAll POST / PATCH / DELETE writes
Read600 / minuteAll GET requests (including /jobs/:id polling)
Exceeding a limit returns 429 with a Retry-After header.

Async jobs

Expensive generation endpoints (/generate/image and /render) are always async. They return 202 Accepted with a jobId immediately — clients then poll GET /jobs/:id for the result. This avoids long-running HTTP requests and stays within Cloudflare Worker CPU limits.
# Kick off the job
curl -X POST https://api.supapost.so/generate/image \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "sunset over tokyo"}'
# → 202 Accepted
# { "jobId": "0b1e...", "status": "pending" }

# Poll the job until it finishes (every 1-2 seconds)
curl https://api.supapost.so/jobs/0b1e... \
  -H "Authorization: Bearer $KEY"
# → { "id": "0b1e...", "type": "image_gen", "status": "completed",
#     "result": { "url": "https://cdn.supapost.so/...jpg" } }
Job status lifecycle: pendingprocessingcompleted | failed. The work runs on Cloudflare Queues with automatic retries and a dead-letter queue for failed messages.

Endpoints

Generation

MethodPathDescription
POST/generate/slidesAI-generate a multi-slide carousel
POST/generate/imageGenerate a single image (always async, returns jobId)
GET/modelsList available image generation models

Rendering

MethodPathDescription
POST/renderRender slides to PNG via Satori + Resvg (always async, returns jobId)

Jobs (async polling)

MethodPathDescription
GET/jobsList recent jobs for the team
GET/jobs/:idGet a single job’s status and result

Projects

MethodPathDescription
GET/projectsList projects
GET/projects/:idGet a project
POST/projectsCreate or update a project
DELETE/projects/:idDelete a project

Scheduling

MethodPathDescription
GET/schedule/postsList scheduled posts
POST/schedule/postsCreate a scheduled post
PATCH/schedule/posts/:idUpdate / reschedule a post
DELETE/schedule/posts/:idDelete a scheduled post

Publishing

MethodPathDescription
POST/publish/tiktokPublish to TikTok drafts

Influencers

MethodPathDescription
GET/influencersList influencers
POST/influencersCreate an influencer
PATCH/influencers/:idUpdate an influencer
DELETE/influencers/:idDelete an influencer

Products

MethodPathDescription
GET/productsList products
GET/products/:idGet a product
POST/productsCreate a product
PATCH/products/:idUpdate a product
DELETE/products/:idDelete a product

Stores (Shopify / Etsy)

MethodPathDescription
GET/storesList connected stores
POST/storesConnect a new store (auto-syncs products)
DELETE/stores/:idDisconnect a store and delete its products
POST/stores/:id/syncRe-sync products from the store

Assets / library

MethodPathDescription
GET/assetsList uploaded + generated assets
POST/uploadUpload a file to the library
POST/upload/presignGet a presigned R2 upload URL
POST/assets/bulk/deleteDelete assets in batches
DELETE/assets/:idDelete an asset
POST/assets/deleteDelete an asset by URL

Team

MethodPathDescription
GET/team/membersList team members
GET/invitesList pending invites

Social accounts

MethodPathDescription
GET/social/accountsList connected social accounts
GET/auth/tiktokStart TikTok OAuth flow
POST/auth/tiktok/disconnectDisconnect a TikTok account
GET/auth/instagramStart Instagram OAuth flow
GET/auth/shopifyStart Shopify OAuth flow

API keys

MethodPathDescription
GET/keysList API keys for the team
POST/keysCreate a new API key
DELETE/keys/:idDelete an API key