# Delete Asset
Source: https://developers.supapost.so/api-reference/assets/delete
DELETE https://api.supapost.so/assets/{id}
Delete an asset by ID
Permanently deletes an asset from both R2 storage and the database. This action cannot be undone.
## Path Parameters
The asset ID (UUID).
## Response
```json 200 theme={null}
{
"success": true
}
```
```json 404 theme={null}
{
"success": false,
"message": "Asset not found"
}
```
***
## Delete Asset by URL
```
POST /assets/delete
```
Delete an asset from R2 storage by its public URL. Useful for cleaning up images that aren't tracked in the assets table (e.g. influencer images, product images).
### Body Parameters
The public R2 URL of the file to delete.
### Response
```json 200 theme={null}
{
"success": true
}
```
# List Assets
Source: https://developers.supapost.so/api-reference/assets/list
GET https://api.supapost.so/assets
List assets for the authenticated team with Stripe-style pagination
Returns assets for the current team, sorted by most recently created. Supports Stripe-style pagination and optional source filtering.
## Authentication
Bearer token. `Bearer `.
## Query Parameters
Filter by asset source. One of `"upload"`, `"ai_generated"`, or `"export"`.
Number of records to return. Maximum `100`.
Return items after this asset ID.
Return items before this asset ID.
```json 200 theme={null}
{
"object": "list",
"data": [
{
"id": "asset-uuid",
"name": "photo.jpg",
"url": "https://cdn.supapost.so/assets/team/photo.jpg",
"content_type": "image/jpeg",
"size_bytes": 245000,
"width": 1080,
"height": 1920,
"source": "upload",
"metadata": null,
"created_at": "2026-04-07T12:00:00Z"
}
],
"has_more": true,
"url": "/assets"
}
```
# Upload File
Source: https://developers.supapost.so/api-reference/assets/upload
POST https://api.supapost.so/upload
Upload a file to asset storage
Upload a file via multipart form data. The file is stored in R2 and tracked in the team's asset library.
## Authentication
Bearer token. `Bearer `.
## Body
Send as `multipart/form-data`.
The file to upload.
Override the filename. Defaults to the original file name.
```json 200 theme={null}
{
"public_url": "https://cdn.supapost.so/assets/team-uuid/1712000000-photo.jpg",
"key": "assets/team-uuid/1712000000-photo.jpg"
}
```
```json 400 theme={null}
{
"success": false,
"message": "file is required"
}
```
# List Credit Packages
Source: https://developers.supapost.so/api-reference/billing/credit-packages
GET /billing/credit-packages
Retrieve the one-time top-up packages available for purchase.
Returns every active top-up pack — a non-expiring credit bundle purchased on top of the monthly plan. Spent AFTER monthly plan credits deplete, so a team with a healthy monthly balance doesn't erode their top-up on the next renewal.
## Response
```json 200 theme={null}
[
{
"id": "pkg-uuid",
"slug": "credits-1k",
"name": "1,000 credits",
"credits": 1000,
"price_cents": 1000,
"offer_price_cents": null,
"savings_pct": null,
"is_active": true,
"sort_order": 10
},
{
"id": "pkg-uuid",
"slug": "credits-5k",
"name": "5,000 credits",
"credits": 5000,
"price_cents": 5000,
"offer_price_cents": 4000,
"savings_pct": 20,
"is_active": true,
"sort_order": 20
}
]
```
### Fields
Number of credits granted on purchase.
Full price in the smallest currency unit (cents for USD).
Discounted price when the pack is promoted. `null` means no offer —
show `price_cents` only.
Rounded-percentage savings vs. `price_cents`. Convenience for badges
like "−20%".
## Example
```bash cURL theme={null}
curl https://api.supapost.so/billing/credit-packages \
-H "Authorization: Bearer YOUR_API_KEY"
```
# Check Team Ownership
Source: https://developers.supapost.so/api-reference/billing/is-owner
GET /billing/is-owner
Whether the authenticated caller is the team owner.
Returns `{ is_owner: true }` when the caller holds the `owner` role on the active team. Several billing actions (subscribing, cancelling, buying top-ups) are owner-only — clients use this to decide whether to show or disable those controls.
## Response
```json 200 theme={null}
{
"is_owner": true
}
```
### Fields
`true` when the caller's `team_members.role` is `owner` on the
currently selected team, `false` otherwise.
## Example
```bash cURL theme={null}
curl https://api.supapost.so/billing/is-owner \
-H "Authorization: Bearer YOUR_API_KEY"
```
# List Ledger Entries
Source: https://developers.supapost.so/api-reference/billing/ledger
GET /billing/ledger
Paginated credit-ledger history for the active team.
Returns the team's credit transactions in reverse-chronological order. Every debit (image/video generation, render) and credit (monthly reset, refund, coupon claim, top-up) is a row. Useful for building a usage dashboard, reconciling end-of-month spend, or surfacing "why did my balance drop?" to the user.
Scoped to the team selected by the caller's session / API key. RLS already enforces team membership.
## Query Parameters
Return rows strictly older than this timestamp. Use the `created_at`
of the last row on the previous page as the cursor.
## Response
```json 200 theme={null}
{
"entries": [
{
"id": 12345,
"delta": -8,
"reason": "image_gen",
"model_id": "fal:nano-banana-pro",
"user_id": "user-uuid",
"route": "/generate/image",
"balance_after": 342,
"metadata": { "job_id": "job-uuid" },
"created_at": "2026-04-21T10:15:00Z",
"auth_mode": "jwt",
"api_key_id": null
}
],
"has_more": true
}
```
### Fields
Signed credit change. Negative for spends, positive for grants /
refunds / top-ups.
One of `image_gen`, `video_gen`, `render`, `monthly_reset`,
`initial_grant`, `plan_change_topup`, `refund`, `admin_grant`,
`coupon_claim`.
Model that incurred the debit, for generation rows. `null` for
non-generation reasons.
Monthly-plan balance immediately after this row was written.
`api_key` (agent / server-to-server), `jwt` (dashboard session), or
`null` (system-issued row like `monthly_reset`).
`true` when more rows exist older than the last returned row. Page
again with `?before=`.
## Example
```bash cURL theme={null}
# First page
curl https://api.supapost.so/billing/ledger \
-H "Authorization: Bearer YOUR_API_KEY"
# Next page
curl "https://api.supapost.so/billing/ledger?before=2026-04-21T10:15:00Z" \
-H "Authorization: Bearer YOUR_API_KEY"
```
# List Plans
Source: https://developers.supapost.so/api-reference/billing/plans
GET /billing/plans
Retrieve the public plan catalog.
Returns every active plan a team can subscribe to. Use it to render pricing pages or to let an agent reason about the upgrade path when credits run low.
## Response
```json 200 theme={null}
[
{
"id": "plan-uuid",
"slug": "starter",
"name": "Starter",
"description": "For hobbyists",
"is_active": true,
"price_cents": 1200,
"currency": "usd",
"monthly_credits": 200,
"allowed_models": ["fal:nano-banana-2"],
"allowed_features": ["influencer"],
"stripe_product_id": "prod_...",
"stripe_price_id": "price_...",
"sort_order": 10
}
]
```
### Fields
URL-safe identifier. Stable across renames of `name`.
Monthly price in the smallest currency unit (cents for USD).
Credits granted at each billing cycle. Resets `credits_remaining`
on `/billing/subscription`.
Model ids this plan can call. A generation request against a model
not in this list returns 403.
Feature surfaces (e.g. `influencer`, `slides`, `broll`, `export`)
the plan includes. Separate from models.
## Example
```bash cURL theme={null}
curl https://api.supapost.so/billing/plans \
-H "Authorization: Bearer YOUR_API_KEY"
```
# Get Subscription
Source: https://developers.supapost.so/api-reference/billing/subscription
GET /billing/subscription
Retrieve the active team's subscription plan and credit balance.
Returns the team's current subscription — plan details, Stripe status, and credit balances (monthly, purchased top-ups, coupon). Agents can call this to check whether a team is billable before enqueuing an expensive job.
Resolves to the team selected by the authenticated caller's session. API-key callers are scoped to the team that owns the key.
## Response
```json 200 theme={null}
{
"plan": {
"id": "plan-uuid",
"slug": "pro",
"name": "Pro",
"description": "For growing creators",
"price_cents": 2900,
"currency": "usd",
"monthly_credits": 500,
"allowed_models": ["fal:nano-banana-pro", "fal:kling-v2.5-pro"],
"allowed_features": ["influencer", "slides"],
"is_active": true,
"sort_order": 20
},
"status": "active",
"cancel_at_period_end": false,
"current_period_end": "2026-05-21T12:00:00Z",
"credits_remaining": 342,
"credits_topup_balance": 1000,
"coupon_credits_balance": 0,
"has_access": true
}
```
### Fields
The plan row. `null` when the team has never had a subscription. See
[List Plans](./plans) for the full plan shape.
Stripe subscription status. One of `trialing`, `active`, `past_due`,
`canceled`, `unpaid`, `incomplete`, `incomplete_expired`, `paused`.
`true` when the subscription will not auto-renew at
`current_period_end`.
ISO-8601 timestamp of the next renewal. Also the date at which
monthly credits reset.
Monthly-plan credits left in the current period. Resets on renewal.
Purchased top-up credits. Non-expiring. Spent AFTER the monthly
balance depletes.
Promotional credits from claimed coupons. Non-expiring.
Computed: `true` when `status ∈ (active, trialing, past_due)` AND
`current_period_end` is in the future. Use this to decide whether a
team can generate, not `status` alone.
## Example
```bash cURL theme={null}
curl https://api.supapost.so/billing/subscription \
-H "Authorization: Bearer YOUR_API_KEY"
```
# Create Influencer
Source: https://developers.supapost.so/api-reference/influencers/create
POST https://api.supapost.so/influencers
Create a new AI influencer
Creates an AI influencer persona with reference images and optional personality traits. The first image in the array is used as the avatar.
## Authentication
Bearer token. `Bearer `.
## Body
Display name for the influencer.
A description of the influencer persona.
Image generation style, e.g. `"realistic"`, `"anime"`, `"3d"`.
AI model identifier for generating images of this influencer.
Array of reference image URLs. The first image is used as the avatar.
Physical and stylistic traits for the influencer. Available fields (all strings): `gender`, `ageRange`, `ethnicity`, `skinTone`, `faceShape`, `jawline`, `eyeColor`, `eyeShape`, `noseShape`, `lipShape`, `facialHair`, `hairColor`, `hairStyle`, `hairLength`, `bodyType`, `height`, `tattoos`, `piercings`, `glasses`, `clothingStyle`, `expression`, `pose`, `lighting`, `background`.
```json 200 theme={null}
{
"id": "inf-uuid",
"team_id": "team-uuid",
"name": "Ava Chen",
"description": "Fitness and wellness influencer",
"style": "realistic",
"model": "fal:flux-pro",
"avatar_url": "https://cdn.supapost.so/assets/team/ava-1.jpg",
"images": [
"https://cdn.supapost.so/assets/team/ava-1.jpg",
"https://cdn.supapost.so/assets/team/ava-2.jpg"
],
"metadata": {
"traits": {
"gender": "female",
"ageRange": "25-30",
"ethnicity": "East Asian",
"skinTone": "light",
"faceShape": "oval",
"jawline": "soft",
"eyeColor": "brown",
"eyeShape": "almond",
"noseShape": "small",
"lipShape": "full",
"facialHair": "none",
"hairColor": "black",
"hairStyle": "straight",
"hairLength": "long",
"bodyType": "athletic",
"height": "tall",
"tattoos": "none",
"piercings": "ears",
"glasses": "none",
"clothingStyle": "athleisure",
"expression": "confident smile",
"pose": "standing",
"lighting": "natural",
"background": "gym"
}
},
"created_by": "user-uuid",
"created_at": "2026-04-08T10:00:00Z",
"updated_at": null
}
```
```json 400 theme={null}
{
"success": false,
"message": "name, description, and images are required"
}
```
# Delete Influencer
Source: https://developers.supapost.so/api-reference/influencers/delete
DELETE /influencers/{id}
Delete an influencer and all associated images.
Permanently deletes an influencer and all associated images from R2 storage. This action cannot be undone.
## Path Parameters
Influencer ID.
## Response
```json 200 theme={null}
{
"success": true
}
```
This deletes the influencer record and removes all generated images from cloud storage.
# List Influencers
Source: https://developers.supapost.so/api-reference/influencers/list
GET https://api.supapost.so/influencers
List all AI influencers for the authenticated team
Returns all influencers for the current team, sorted by most recently created.
## Authentication
Bearer token. `Bearer `.
```json 200 theme={null}
[
{
"id": "inf-uuid",
"team_id": "team-uuid",
"name": "Ava Chen",
"description": "Fitness and wellness influencer",
"style": "realistic",
"model": "fal:flux-pro",
"avatar_url": "https://cdn.supapost.so/assets/team/ava-1.jpg",
"images": [
"https://cdn.supapost.so/assets/team/ava-1.jpg",
"https://cdn.supapost.so/assets/team/ava-2.jpg"
],
"metadata": {
"traits": {
"tone": "motivational",
"niche": "fitness"
}
},
"created_by": "user-uuid",
"created_at": "2026-04-01T12:00:00Z",
"updated_at": "2026-04-07T15:30:00Z"
}
]
```
# Update Influencer
Source: https://developers.supapost.so/api-reference/influencers/update
PATCH /influencers/{id}
Update an existing influencer's details or images.
## Path Parameters
Influencer ID.
## Body Parameters
All fields are optional. Only provided fields will be updated.
Influencer name.
Description / prompt used to generate.
Art style: `realistic`, `anime`, `3d`, `fashion`, `minimal`.
AI model used (e.g. `fal:flux-pro`, `higgsfield:soul`).
Array of image URLs. The first image is used as the avatar.
Character traits (demographics, face, hair, body, style).
## Response
```json 200 theme={null}
{
"id": "inf-uuid",
"name": "Amy",
"description": "A young woman...",
"style": "realistic",
"model": "fal:flux-pro",
"images": ["https://cdn.supapost.so/assets/...", "..."],
"updated_at": "2026-04-09T12:00:00Z"
}
```
# Get Job
Source: https://developers.supapost.so/api-reference/jobs/get
GET https://api.supapost.so/jobs/{id}
Poll the status of an async job
Returns the status and (if completed) result of an async job. Use this endpoint to poll jobs created by passing `?async=true` to `/generate/image` or `/render`.
## Authentication
Bearer token. `Bearer `.
## Path Parameters
The job ID returned by the `?async=true` endpoint.
## Lifecycle
Jobs progress through these states:
* `pending` — queued, not yet picked up by a consumer
* `processing` — actively generating
* `completed` — finished, `result` is populated
* `failed` — something went wrong, `error` is populated
Polling: client-side code typically polls every 1–2 seconds until `status` is `completed` or `failed`.
```json 200 (processing) theme={null}
{
"id": "0b1e9a5f-1234-4d8c-b2a0-...",
"type": "image_gen",
"status": "processing",
"result": null,
"error": null,
"created_at": "2026-04-11T10:00:00Z",
"updated_at": "2026-04-11T10:00:02Z"
}
```
```json 200 (completed) theme={null}
{
"id": "0b1e9a5f-1234-4d8c-b2a0-...",
"type": "image_gen",
"status": "completed",
"result": {
"url": "https://cdn.supapost.so/assets/team-uuid/1712000000-generated.jpg",
"width": 1080,
"height": 1920,
"content_type": "image/jpeg"
},
"error": null,
"created_at": "2026-04-11T10:00:00Z",
"updated_at": "2026-04-11T10:00:08Z"
}
```
```json 200 (failed) theme={null}
{
"id": "0b1e9a5f-1234-4d8c-b2a0-...",
"type": "image_gen",
"status": "failed",
"result": null,
"error": "nsfw content detected",
"created_at": "2026-04-11T10:00:00Z",
"updated_at": "2026-04-11T10:00:04Z"
}
```
```json 404 theme={null}
{
"success": false,
"message": "Job not found"
}
```
# List Jobs
Source: https://developers.supapost.so/api-reference/jobs/list
GET https://api.supapost.so/jobs
List recent async jobs for your team
Returns the 50 most recent jobs for the authenticated team, ordered by creation time descending.
## Authentication
Bearer token. `Bearer `.
## Query Parameters
Filter by job type. One of: `image_gen`, `render`, `publish`.
Filter by status. One of: `pending`, `processing`, `completed`, `failed`.
```json 200 theme={null}
[
{
"id": "0b1e9a5f-...",
"type": "image_gen",
"status": "completed",
"result": {
"url": "https://cdn.supapost.so/assets/team-uuid/1712000000-generated.jpg",
"width": 1080,
"height": 1920,
"content_type": "image/jpeg"
},
"error": null,
"created_at": "2026-04-11T10:00:00Z",
"updated_at": "2026-04-11T10:00:08Z"
}
]
```
# API Overview
Source: https://developers.supapost.so/api-reference/overview
REST API reference for Supapost.
## 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:
```bash theme={null}
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](/authentication) for details.
## Response format
Every response uses a consistent JSON shape.
**Success** — the data directly (or a domain-specific envelope):
```json theme={null}
{ "id": "abc", "name": "Morning routine" }
```
**Error** — always `success: false` plus a human-readable `message`:
```json theme={null}
{ "success": false, "message": "name is required" }
```
## Pagination
Paginated list endpoints use a Stripe-style contract:
```json theme={null}
{
"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
| Code | Meaning |
| ---- | -------------------------------------------------------- |
| 200 | Success |
| 202 | Accepted — async job queued, poll `/jobs/:id` for result |
| 400 | Bad request — the `message` field explains what |
| 401 | Missing or invalid credentials |
| 403 | Authenticated but not authorized for this resource |
| 404 | Not found |
| 429 | Rate limit exceeded — see `Retry-After` header |
| 500 | Internal server error |
| 502 | Upstream provider error (FAL, Higgsfield, TikTok, etc.) |
## Rate limits
Limits are per-team, bucketed by endpoint tier:
| Tier | Limit | Endpoints |
| --------- | ------------ | -------------------------------------------------------------------- |
| Expensive | 30 / minute | `/generate/slides`, `/generate/image`, `/render`, `/stores/:id/sync` |
| Mutating | 120 / minute | All POST / PATCH / DELETE writes |
| Read | 600 / minute | All 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 `job_id` immediately — clients then poll `GET /jobs/:id` for the result. This avoids long-running HTTP requests and stays within Cloudflare Worker CPU limits.
```bash theme={null}
# 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
# { "job_id": "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: `pending` → `processing` → `completed | failed`.
The work runs on Cloudflare Queues with automatic retries and a dead-letter queue for failed messages.
## Endpoints
### Generation
| Method | Path | Description |
| ------ | ------------------ | -------------------------------------------------------- |
| POST | `/generate/slides` | AI-generate a multi-slide carousel |
| POST | `/generate/image` | Generate a single image (always async, returns `job_id`) |
| GET | `/models` | List available image generation models |
### Rendering
| Method | Path | Description |
| ------ | --------- | ------------------------------------------------------------------------ |
| POST | `/render` | Render slides to PNG via Satori + Resvg (always async, returns `job_id`) |
### Jobs (async polling)
| Method | Path | Description |
| ------ | ----------- | ------------------------------------ |
| GET | `/jobs` | List recent jobs for the team |
| GET | `/jobs/:id` | Get a single job's status and result |
### Projects
| Method | Path | Description |
| ------ | --------------- | -------------------------- |
| GET | `/projects` | List projects |
| GET | `/projects/:id` | Get a project |
| POST | `/projects` | Create or update a project |
| DELETE | `/projects/:id` | Delete a project |
### Scheduling
| Method | Path | Description |
| ------ | --------------------- | -------------------------- |
| GET | `/schedule/posts` | List scheduled posts |
| POST | `/schedule/posts` | Create a scheduled post |
| PATCH | `/schedule/posts/:id` | Update / reschedule a post |
| DELETE | `/schedule/posts/:id` | Delete a scheduled post |
### Publishing
| Method | Path | Description |
| ------ | ----------------- | ------------------------ |
| POST | `/publish/tiktok` | Publish to TikTok drafts |
### Influencers
| Method | Path | Description |
| ------ | ------------------ | -------------------- |
| GET | `/influencers` | List influencers |
| POST | `/influencers` | Create an influencer |
| PATCH | `/influencers/:id` | Update an influencer |
| DELETE | `/influencers/:id` | Delete an influencer |
### Products
| Method | Path | Description |
| ------ | --------------- | ---------------- |
| GET | `/products` | List products |
| GET | `/products/:id` | Get a product |
| POST | `/products` | Create a product |
| PATCH | `/products/:id` | Update a product |
| DELETE | `/products/:id` | Delete a product |
### Stores (Shopify / Etsy)
| Method | Path | Description |
| ------ | ------------------ | ------------------------------------------ |
| GET | `/stores` | List connected stores |
| POST | `/stores` | Connect a new store (auto-syncs products) |
| DELETE | `/stores/:id` | Disconnect a store and delete its products |
| POST | `/stores/:id/sync` | Re-sync products from the store |
### Assets / library
| Method | Path | Description |
| ------ | --------------------- | -------------------------------- |
| GET | `/assets` | List uploaded + generated assets |
| POST | `/upload` | Upload a file to the library |
| POST | `/upload/presign` | Get a presigned R2 upload URL |
| POST | `/assets/bulk/delete` | Delete assets in batches |
| DELETE | `/assets/:id` | Delete an asset |
| POST | `/assets/delete` | Delete an asset by URL |
### Team
| Method | Path | Description |
| ------ | --------------- | -------------------- |
| GET | `/team/members` | List team members |
| GET | `/invites` | List pending invites |
### Social accounts
| Method | Path | Description |
| ------ | ------------------------- | ------------------------------ |
| GET | `/social/accounts` | List connected social accounts |
| GET | `/auth/tiktok` | Start TikTok OAuth flow |
| POST | `/auth/tiktok/disconnect` | Disconnect a TikTok account |
| GET | `/auth/instagram` | Start Instagram OAuth flow |
| GET | `/auth/shopify` | Start Shopify OAuth flow |
### API keys
| Method | Path | Description |
| ------ | ----------- | -------------------------- |
| GET | `/keys` | List API keys for the team |
| POST | `/keys` | Create a new API key |
| DELETE | `/keys/:id` | Delete an API key |
# Create Product
Source: https://developers.supapost.so/api-reference/products/create
POST /products
Create a new product manually.
## Body Parameters
Product name.
Product description.
Product price.
Original price for showing discounts.
Currency code (e.g. `USD`, `EUR`, `GBP`).
Stock keeping unit.
Product status: `active`, `draft`, or `archived`.
Primary product image URL.
External product page URL.
## Response
```json 200 theme={null}
{
"id": "prod-uuid",
"name": "Classic T-Shirt",
"price": 29.99,
"currency": "USD",
"status": "active",
"created_at": "2026-04-08T18:00:00Z"
}
```
# Delete Product
Source: https://developers.supapost.so/api-reference/products/delete
DELETE /products/{id}
Delete a product.
## Path Parameters
Product ID.
## Response
```json 200 theme={null}
{
"success": true
}
```
# List Products
Source: https://developers.supapost.so/api-reference/products/list
GET /products
Retrieve products for your team with Stripe-style pagination.
## Query Parameters
Number of records to return. Maximum `100`.
Return items after this product ID.
Return items before this product ID.
Filter by connected store ID.
Filter by status: `active`, `draft`, or `archived`.
## Response
```json 200 theme={null}
{
"object": "list",
"data": [
{
"id": "prod-uuid",
"name": "Classic T-Shirt",
"description": "100% cotton crew neck",
"price": 29.99,
"compare_at_price": null,
"currency": "USD",
"sku": "TSH-001",
"status": "active",
"image_url": "https://cdn.example.com/tshirt.jpg",
"images": ["https://cdn.example.com/tshirt.jpg"],
"product_url": "https://my-store.myshopify.com/products/classic-tshirt",
"store_id": "store-uuid",
"external_product_id": "123456789",
"team_stores": {
"store_name": "My Store",
"store_domain": "my-store.myshopify.com",
"platform": "shopify"
},
"created_at": "2026-04-08T18:00:00Z"
}
],
"has_more": true,
"url": "/products"
}
```
# Update Product
Source: https://developers.supapost.so/api-reference/products/update
PATCH /products/{id}
Update an existing product.
## Path Parameters
Product ID.
## Body Parameters
All fields are optional. Only provided fields will be updated.
Product name.
Product description.
Product price.
Compare at price.
Currency code.
Stock keeping unit.
Status: `active`, `draft`, or `archived`.
Primary image URL.
External product URL.
## Response
```json 200 theme={null}
{
"id": "prod-uuid",
"name": "Classic T-Shirt",
"price": 24.99,
"status": "active",
"updated_at": "2026-04-08T19:00:00Z"
}
```
# Delete Project
Source: https://developers.supapost.so/api-reference/projects/delete
DELETE https://api.supapost.so/projects/{id}
Delete a project by ID
Permanently deletes a project. This action cannot be undone.
## Authentication
Bearer token. `Bearer `.
## Path Parameters
The project ID (UUID).
```json 200 theme={null}
{
"success": true
}
```
# Get Project
Source: https://developers.supapost.so/api-reference/projects/get
GET https://api.supapost.so/projects/{id}
Get a single project by ID
Returns the full project record including all project data.
## Authentication
Bearer token. `Bearer `.
## Path Parameters
The project ID (UUID).
```json 200 theme={null}
{
"id": "uuid-1234",
"team_id": "team-uuid",
"name": "Morning Routine Carousel",
"type": "slideshow",
"data": { },
"thumbnail_url": "https://cdn.supapost.so/assets/team/thumb.jpg",
"status": "draft",
"created_by": "user-uuid",
"created_at": "2026-04-01T12:00:00Z",
"updated_at": "2026-04-07T15:30:00Z"
}
```
```json 404 theme={null}
{
"success": false,
"message": "Project not found"
}
```
# List Projects
Source: https://developers.supapost.so/api-reference/projects/list
GET https://api.supapost.so/projects
List all projects for the authenticated team
Returns all projects for the current team, sorted by most recently updated.
## Authentication
Bearer token. `Bearer `.
## Query Parameters
Filter projects by type, e.g. `"slideshow"`.
```json 200 theme={null}
[
{
"id": "uuid-1234",
"name": "Morning Routine Carousel",
"type": "slideshow",
"thumbnail_url": "https://cdn.supapost.so/assets/team/thumb.jpg",
"status": "draft",
"created_at": "2026-04-01T12:00:00Z",
"updated_at": "2026-04-07T15:30:00Z"
}
]
```
# Create or Update Project
Source: https://developers.supapost.so/api-reference/projects/save
POST https://api.supapost.so/projects
Create a new project or update an existing one
If `id` is provided, updates the existing project. Otherwise creates a new project.
## Authentication
Bearer token. `Bearer `.
## Body
Project ID to update. Omit to create a new project.
Display name for the project.
Project type, e.g. `"slideshow"`.
The full project data (slides, texts, images, etc.). Schema is type-dependent.
URL for the project thumbnail.
Project status. Defaults to `"draft"`.
```json 200 theme={null}
{
"id": "uuid-1234",
"team_id": "team-uuid",
"name": "Morning Routine Carousel",
"type": "slideshow",
"data": { },
"thumbnail_url": "https://cdn.supapost.so/assets/team/thumb.jpg",
"status": "draft",
"created_by": "user-uuid",
"created_at": "2026-04-01T12:00:00Z",
"updated_at": "2026-04-08T10:00:00Z"
}
```
# Publish to TikTok
Source: https://developers.supapost.so/api-reference/publishing/tiktok
POST https://api.supapost.so/publish/tiktok
Publish a slideshow to TikTok as a photo post
Publishes images to a connected TikTok account. The post is sent to TikTok drafts for final review before going live.
## Authentication
Bearer token. `Bearer `.
## Body
ID of the connected TikTok social account.
Array of image URLs to include in the slideshow.
Caption for the TikTok post.
```json 200 theme={null}
{
"success": true,
"message": "Slideshow sent to TikTok drafts!",
"publish_id": "tiktok-publish-id"
}
```
```json 400 theme={null}
{
"success": false,
"message": "account_id and image_urls are required"
}
```
```json 404 theme={null}
{
"success": false,
"message": "TikTok account not found"
}
```
# Render Slides
Source: https://developers.supapost.so/api-reference/render
POST https://api.supapost.so/render
Queue a slide rendering job
Renders an array of slide definitions to PNG images via Satori + Resvg, uploads them to R2, and returns the public URLs through the job result.
**This endpoint is always async** — it returns a `job_id` immediately and the actual rendering happens on a background queue. Poll [`GET /jobs/:id`](/api-reference/jobs/get) until `status` is `completed`, then read `result.slides`.
## Authentication
Bearer token. `Bearer `.
## Body
Array of slide definitions. Each slide has a `name` and `background`.
Array of text layers to place on slides. Each entry has `slide_index` and a `text` object with full styling (see [Generate Slides](/api-reference/slides/generate) for the full text schema).
Optional array of background image overrides. Each entry has `slide_index` and `image_url`. When provided, the slide's background type is set to `image`.
## Polling pattern
```bash theme={null}
# 1. Submit
curl -X POST https://api.supapost.so/render \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"slides": [...], "texts": [...]}'
# → 202 { "job_id": "0b1e...", "status": "pending" }
# 2. Poll every 1-2 seconds
curl https://api.supapost.so/jobs/0b1e... \
-H "Authorization: Bearer $KEY"
# → { "status": "processing" }
# → { "status": "completed", "result": { "slides": [{ "name": "...", "image_url": "..." }] } }
```
```json 202 theme={null}
{
"job_id": "0b1e9a5f-...",
"status": "pending"
}
```
```json 400 theme={null}
{
"success": false,
"message": "slides are required"
}
```
# Create Scheduled Post
Source: https://developers.supapost.so/api-reference/scheduling/create
POST https://api.supapost.so/schedule/posts
Schedule a post for future publishing
Creates a new scheduled post. The `scheduled_at` time must be in the future. A cron job will automatically publish the post at the scheduled time.
## Authentication
Bearer token. `Bearer `.
## Body
ID of the connected social account to publish to.
Target platform, e.g. `"tiktok"`.
ISO 8601 datetime for when the post should be published. Must be in the future.
Optional project ID to link this post to.
Title or caption for the post.
Array of image URLs to include in the post.
```json 200 theme={null}
{
"id": "post-uuid",
"team_id": "team-uuid",
"project_id": "proj-uuid",
"social_account_id": "acct-uuid",
"platform": "tiktok",
"scheduled_at": "2026-04-10T14:00:00Z",
"title": "Morning Routine Tips",
"image_urls": ["https://cdn.supapost.so/assets/team/slide1.jpg"],
"status": "scheduled",
"project": {
"id": "proj-uuid",
"name": "Morning Routine Carousel",
"thumbnail_url": "https://cdn.supapost.so/assets/team/thumb.jpg"
},
"account": {
"id": "acct-uuid",
"platform": "tiktok",
"platform_username": "myaccount",
"display_name": "My Account",
"avatar_url": "https://example.com/avatar.jpg"
}
}
```
```json 400 theme={null}
{
"success": false,
"message": "scheduled_at must be in the future"
}
```
# Delete Scheduled Post
Source: https://developers.supapost.so/api-reference/scheduling/delete
DELETE https://api.supapost.so/schedule/posts/{id}
Delete a scheduled post
Permanently removes a scheduled post. This action cannot be undone.
## Authentication
Bearer token. `Bearer `.
## Path Parameters
The scheduled post ID (UUID).
```json 200 theme={null}
{
"success": true
}
```
# List Scheduled Posts
Source: https://developers.supapost.so/api-reference/scheduling/list
GET https://api.supapost.so/schedule/posts
List all scheduled posts for the authenticated team
Returns scheduled posts sorted by scheduled time (ascending). Includes related project and social account data.
## Authentication
Bearer token. `Bearer `.
## Query Parameters
ISO 8601 datetime. Only return posts scheduled at or after this time.
ISO 8601 datetime. Only return posts scheduled at or before this time.
Filter by status, e.g. `"scheduled"`, `"published"`, `"failed"`.
```json 200 theme={null}
[
{
"id": "post-uuid",
"team_id": "team-uuid",
"project_id": "proj-uuid",
"social_account_id": "acct-uuid",
"platform": "tiktok",
"scheduled_at": "2026-04-10T14:00:00Z",
"title": "Morning Routine Tips",
"image_urls": ["https://cdn.supapost.so/assets/team/slide1.jpg"],
"status": "scheduled",
"project": {
"id": "proj-uuid",
"name": "Morning Routine Carousel",
"thumbnail_url": "https://cdn.supapost.so/assets/team/thumb.jpg"
},
"account": {
"id": "acct-uuid",
"platform": "tiktok",
"platform_username": "myaccount",
"display_name": "My Account",
"avatar_url": "https://example.com/avatar.jpg"
}
}
]
```
# Update Scheduled Post
Source: https://developers.supapost.so/api-reference/scheduling/update
PATCH https://api.supapost.so/schedule/posts/{id}
Update a scheduled post
Update the time, title, or status of a scheduled post. Only posts with `"scheduled"` status can be updated.
## Authentication
Bearer token. `Bearer `.
## Path Parameters
The scheduled post ID (UUID).
## Body
New ISO 8601 datetime for publishing.
Updated title or caption.
Updated status value.
```json 200 theme={null}
{
"id": "post-uuid",
"team_id": "team-uuid",
"scheduled_at": "2026-04-12T10:00:00Z",
"title": "Updated Title",
"status": "scheduled",
"updated_at": "2026-04-08T09:00:00Z"
}
```
```json 404 theme={null}
{
"success": false,
"message": "Post not found or not editable"
}
```
# Generate Slides
Source: https://developers.supapost.so/api-reference/slides/generate
POST https://api.supapost.so/generate/slides
Generate a TikTok slideshow with AI-created backgrounds and text overlays
An AI agent creates a multi-slide carousel from a text prompt. The agent generates gradient backgrounds, AI background images (via FLUX), and positioned text elements for each slide on a 1080x1920 canvas.
## Authentication
Bearer token. `Bearer `.
## Body
Description of the slideshow you want to create. For example: "5-slide motivational carousel about morning routines".
```json 200 theme={null}
{
"slides": [
{
"name": "Intro",
"background": {
"type": "gradient",
"gradientFrom": "#1a1a2e",
"gradientTo": "#16213e",
"gradientAngle": 135
}
}
],
"texts": [
{
"slide_index": 0,
"text": {
"content": "Rise & Grind",
"fontSize": 96,
"fontWeight": 800,
"x": 90,
"y": 800,
"width": 900,
"color": "#ffffff",
"textAlign": "center",
"lineHeight": 1.2,
"letterSpacing": 0,
"textTransform": "none",
"textShadow": {
"enabled": true,
"color": "#000000",
"offsetX": 2,
"offsetY": 2,
"blur": 4
},
"textBackground": {
"enabled": true,
"color": "#000000",
"paddingX": 12,
"paddingY": 6
},
"textStroke": {
"enabled": false,
"color": "#000000",
"width": 2
}
}
}
],
"images": [
{
"slide_index": 0,
"image_url": "https://cdn.supapost.so/assets/team123/1712000000-bg-slide-1.jpg"
}
]
}
```
# Generate Image
Source: https://developers.supapost.so/api-reference/slides/image
POST https://api.supapost.so/generate/image
Queue an image generation job
Generates an image from a text prompt. **This endpoint is always async** — it returns a `job_id` immediately and the actual generation happens on a background queue. Poll [`GET /jobs/:id`](/api-reference/jobs/get) until `status` is `completed`, then read `result.url`.
The completed image is automatically uploaded to R2 storage and saved to the team's asset library.
## Authentication
Bearer token. `Bearer `.
## Body
Text description of the image to generate.
Model identifier in `provider:model` format. Use `GET /models` to list options.
Aspect ratio for the generated image, e.g. `"9:16"`, `"1:1"`, `"16:9"`.
URL of a reference image for image-to-image generation.
How closely to follow the reference image (0-1). Only used when `reference_image_url` is provided.
If provided, the completed image is automatically appended to this influencer's image array. Survives the user navigating away mid-generation.
## Polling pattern
```bash theme={null}
# 1. Submit
curl -X POST https://api.supapost.so/generate/image \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "sunset over tokyo", "aspect_ratio": "9:16"}'
# → 202 { "job_id": "0b1e...", "status": "pending" }
# 2. Poll every 1-2 seconds
curl https://api.supapost.so/jobs/0b1e... \
-H "Authorization: Bearer $KEY"
# → { "status": "processing", ... }
# → { "status": "completed", "result": { "url": "https://cdn.supapost.so/...jpg" } }
```
```json 202 theme={null}
{
"job_id": "0b1e9a5f-1234-4d8c-b2a0-...",
"status": "pending"
}
```
```json 400 theme={null}
{
"success": false,
"message": "prompt is required"
}
```
```json 429 theme={null}
{
"success": false,
"message": "Rate limit exceeded for expensive endpoints. Retry in 60s."
}
```
# Disconnect Store
Source: https://developers.supapost.so/api-reference/stores/disconnect
DELETE /stores/{id}
Disconnect an e-commerce store and remove all synced products.
## Path Parameters
Store ID.
## Response
```json 200 theme={null}
{
"success": true
}
```
This removes all products that were synced from this store. It does not affect your actual e-commerce store.
# List Stores
Source: https://developers.supapost.so/api-reference/stores/list
GET /stores
List all connected e-commerce stores.
## Response
```json 200 theme={null}
[
{
"id": "store-uuid",
"platform": "shopify",
"store_domain": "my-store.myshopify.com",
"store_name": "My Store",
"last_synced_at": "2026-04-08T18:30:00Z",
"created_at": "2026-04-08T18:00:00Z"
}
]
```
# Sync Store Products
Source: https://developers.supapost.so/api-reference/stores/sync
POST /stores/{id}/sync
Trigger a product sync from a connected store.
## Path Parameters
Store ID.
## Response
```json 200 theme={null}
{
"synced": 18
}
```
The `synced` field indicates how many products were synced from the store.
# List Invites
Source: https://developers.supapost.so/api-reference/team/invites-list
GET /invites
Retrieve pending team invites with Stripe-style pagination.
## Query Parameters
Number of records to return. Maximum `100`.
Return items after this invite ID.
Return items before this invite ID.
## Response
```json 200 theme={null}
{
"object": "list",
"data": [
{
"id": "invite-uuid",
"email": "teammate@example.com",
"role": "member",
"invited_by": "user-uuid",
"expires_at": "2026-04-15T18:00:00Z",
"accepted_at": null,
"created_at": "2026-04-08T18:00:00Z"
}
],
"has_more": true,
"url": "/invites"
}
```
# List Team Members
Source: https://developers.supapost.so/api-reference/team/members-list
GET /team/members
Retrieve team members with Stripe-style pagination.
## Query Parameters
Number of records to return. Maximum `100`.
Return items after this member ID.
Return items before this member ID.
## Response
```json 200 theme={null}
{
"object": "list",
"data": [
{
"id": "member-uuid",
"user_id": "user-uuid",
"role": "admin",
"created_at": "2026-04-08T18:00:00Z",
"email": "teammate@example.com",
"full_name": "Alex Example",
"avatar_url": "https://example.com/avatar.jpg"
}
],
"has_more": true,
"url": "/team/members"
}
```
# Authentication
Source: https://developers.supapost.so/authentication
How to authenticate with the Supapost API.
The Supapost API supports two authentication methods.
## API key
For server-to-server integrations, use an API key. Create one in **Settings → Developer** in the dashboard — keys are prefixed `sp_live_...` and scoped to your team.
```bash theme={null}
curl https://api.supapost.so/projects \
-H "Authorization: Bearer sp_live_..."
```
API keys are verified through [Unkey](https://unkey.dev) on every request and inherit all permissions of the team owner (full access to team resources).
## Supabase JWT
The web app authenticates via Supabase JWT tokens. The frontend manages these automatically — you only need to handle them yourself when building a custom integration against the same backend.
```bash theme={null}
curl https://api.supapost.so/projects \
-H "Authorization: Bearer eyJhbGci..."
```
Tokens are verified against the Supabase project's public JWKS (ES256). No shared secret is required.
## Unauthenticated endpoints
A small number of routes are intentionally public:
| Path | Purpose |
| ---------------------------------- | ------------------------------------------------------------------------------------------ |
| `GET /health` | Liveness probe |
| `GET /auth/tiktok/callback` | TikTok OAuth redirect (state token verified via KV) |
| `GET /auth/instagram/callback` | Instagram OAuth redirect |
| `GET /auth/shopify/callback` | Shopify OAuth redirect |
| `POST /webhooks/higgsfield/:jobId` | Higgsfield image-generation callback — protected by a per-job nonce in the `?token=` query |
All other routes require an `Authorization: Bearer ...` header and will return `401` without one.
## Rate limits
Limits are applied per-team across three buckets:
| Tier | Limit | Endpoints |
| --------- | ------------ | -------------------------------------------------------------------- |
| Expensive | 30 / minute | `/generate/slides`, `/generate/image`, `/render`, `/stores/:id/sync` |
| Mutating | 120 / minute | All POST / PATCH / DELETE writes |
| Read | 600 / minute | All GET requests |
Exceeding a limit returns a `429` response with a `Retry-After` header indicating when to retry:
```json theme={null}
{
"success": false,
"message": "Rate limit exceeded for expensive endpoints. Retry in 60s."
}
```
Rate limits are enforced by [Cloudflare's native rate-limiting API](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/). Counters reset every 60 seconds.
# Influencers
Source: https://developers.supapost.so/guides/influencers
Create AI-generated influencer personas with character consistency.
## Overview
The Influencer Studio lets you create consistent AI-generated personas for your content. Define a character's appearance and style, generate images, and maintain visual consistency across all future generations — regardless of which AI model you use.
## Creating an Influencer
1. Open **Studio > Influencers** in the dashboard
2. Click **+** to create a new influencer
3. Set the character traits in the **Properties** panel (demographics, face, hair, body)
4. Type a scene description (e.g. "smiling, casual outfit")
5. Select an AI model and click **Generate**
6. The first image defines the character — click **Save** to persist
## Character Consistency
After the first image is generated, all subsequent images automatically maintain the same character identity:
* The first image is used as a **character reference** sent to the AI model
* You only need to describe the **scene** (e.g. "on the beach", "in a coffee shop") — no need to re-describe the character
* This works across **all supported models**: Flux Pro, Nano Banana, Higgsfield Soul
* Each model uses its native reference image format for best results
### How it works per model
| Model | Reference Method |
| ----------------- | -------------------------------------------- |
| Flux Pro | Kontext image-to-image with `image_url` |
| Flux Dev/Schnell | Image-to-image with `image_url` + `strength` |
| Nano Banana Pro/2 | Edit endpoint with `image_urls` array |
| Higgsfield Soul | `reference_image_urls` array |
### Using Product References
You can also use product images as references alongside character consistency:
1. Click **Reference** in the prompt bar
2. Switch to the **Products** tab
3. Select a product image (e.g. a perfume bottle)
4. Type your scene: "holding the product in a studio"
The character stays consistent while the product appears in the scene.
## Structured Prompts
For the first image (character creation), Supapost sends a **JSON-structured prompt** to the AI model. This format produces more consistent and accurate results than plain text:
```json theme={null}
{
"subject": { "type": "person", "gender": "female", "age": "18-24", "ethnicity": "White" },
"face": { "shape": "Heart", "eye_color": "Blue", "expression": "neutral" },
"hair": { "color": "Brown", "length": "Long", "style": "Wavy" },
"scene": "portrait, looking at camera",
"style": "Ultra realistic photography, professional portrait",
"camera": { "angle": "eye level", "lens": "85mm", "aperture": "f/2.8" }
}
```
After the first image, subsequent prompts are just the scene description (e.g. "on a tropical beach") since the model gets the character from the reference image.
## Managing Images
* **Click an image** to open the fullscreen lightbox with metadata (model, prompt, timestamp)
* **Arrow keys** to navigate between images
* **Download** individual images
* **Delete** individual images (removes from R2 storage)
* **Delete influencer** removes all images and the influencer record
## Art Styles
| Style | Description |
| --------- | -------------------------------------------- |
| Realistic | Ultra-realistic photography, studio lighting |
| Anime | Vibrant anime illustration style |
| 3D | Pixar-quality 3D rendered character |
| Fashion | High fashion editorial photography |
| Minimal | Clean, soft lighting, muted tones |
## API Usage
### List Influencers
```bash theme={null}
curl https://api.supapost.so/influencers \
-H "Authorization: Bearer YOUR_API_KEY"
```
### Create Influencer
```bash theme={null}
curl -X POST https://api.supapost.so/influencers \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Luna",
"description": "Young woman with brown hair",
"style": "realistic",
"model": "fal:flux-pro",
"images": ["https://cdn.supapost.so/..."],
"traits": { "gender": "Female", "ageRange": "18-24" }
}'
```
### Update Influencer (add images)
```bash theme={null}
curl -X PATCH https://api.supapost.so/influencers/INFLUENCER_UUID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"images": ["https://cdn.supapost.so/img1.jpg", "https://cdn.supapost.so/img2.jpg", "https://cdn.supapost.so/new-img.jpg"]
}'
```
When updating images, send the **full array** including existing images. The first image is always used as the avatar and character reference.
### Delete Influencer
```bash theme={null}
curl -X DELETE https://api.supapost.so/influencers/INFLUENCER_UUID \
-H "Authorization: Bearer YOUR_API_KEY"
```
This permanently deletes the influencer and all associated images from storage.
### Delete Individual Image
To remove a single image, update the influencer with the image removed from the array, then delete the file from R2:
```bash theme={null}
# 1. Update influencer images (without the deleted one)
curl -X PATCH https://api.supapost.so/influencers/INFLUENCER_UUID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "images": ["https://cdn.supapost.so/img1.jpg", "https://cdn.supapost.so/img2.jpg"] }'
# 2. Delete the image file from R2
curl -X POST https://api.supapost.so/assets/delete \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://cdn.supapost.so/removed-img.jpg" }'
```
# Products
Source: https://developers.supapost.so/guides/products
Create products manually or sync from e-commerce stores like Shopify and Etsy.
## Overview
Products let you manage your catalog within Supapost. You can create products manually or connect your e-commerce stores (Shopify, Etsy) to automatically sync your product catalog.
Products can be used in your content — reference them in slides, schedule product-focused posts, and track which products you're promoting.
## Creating Products Manually
1. Go to **Products** in the sidebar
2. Click **Add Product**
3. Fill in the product details in the right-side panel:
* **Name** (required)
* **Description**
* **Price** and **Compare at Price**
* **Currency** and **Status** (Active, Draft, Archived)
* **SKU**, **Image URL**, **Product URL**
4. Click **Create Product**
## Connecting a Store
Supapost supports connecting e-commerce stores to automatically import your products.
### Supported Platforms
| Platform | Auth Method | Status |
| ----------- | ----------------- | ----------- |
| Shopify | OAuth (one-click) | Available |
| Etsy | API Key | Available |
| WooCommerce | — | Coming soon |
| Amazon | — | Coming soon |
### Connecting Shopify
Shopify uses OAuth — no access tokens to copy/paste.
1. Go to **Products** and click **Connect Store**
2. Select **Shopify**
3. Enter your store domain (e.g. `my-store` or `my-store.myshopify.com`)
4. Click **Continue to Shopify**
5. You'll be redirected to Shopify to authorize Supapost with `read_products` access
6. After approving, you'll be redirected back and your products will sync automatically
Shopify requires a Supapost app to be installed. Supapost only requests `read_products` scope — it cannot modify your Shopify store.
### Connecting Etsy
Etsy uses an API key for authentication.
1. Go to **Products** and click **Connect Store**
2. Select **Etsy**
3. Enter your Etsy Shop ID and API Key
4. Click **Connect & Sync Products**
You can get your API key from the [Etsy Developer Portal](https://developers.etsy.com).
## Syncing Products
When you connect a store, products are synced automatically. You can re-sync at any time:
1. Open **Settings** (gear icon in the sidebar header)
2. Go to the **Connected Stores** section
3. Click **Sync Now** on any store
Syncing pulls the latest products from your store and updates existing records. New products are added, and existing products are updated with the latest price, inventory, and images.
## Managing Stores
All connected stores are managed from the **Settings** dialog (gear icon in the sidebar header):
* **Sync Now** — re-fetch all products from the store
* **Disconnect** — removes the store connection and all synced products from Supapost (does not affect your actual store)
## Products via API
### List Products
```bash theme={null}
curl https://api.supapost.so/products \
-H "Authorization: Bearer YOUR_API_KEY"
```
Filter by store or status:
```bash theme={null}
# Filter by store
curl "https://api.supapost.so/products?store_id=STORE_UUID" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by status
curl "https://api.supapost.so/products?status=active" \
-H "Authorization: Bearer YOUR_API_KEY"
```
### Create a Product
```bash theme={null}
curl -X POST https://api.supapost.so/products \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Classic T-Shirt",
"description": "100% cotton crew neck",
"price": 29.99,
"currency": "USD",
"sku": "TSH-001",
"status": "active",
"image_url": "https://example.com/tshirt.jpg"
}'
```
### Update a Product
```bash theme={null}
curl -X PATCH https://api.supapost.so/products/PRODUCT_UUID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"price": 24.99,
"status": "active"
}'
```
### Delete a Product
```bash theme={null}
curl -X DELETE https://api.supapost.so/products/PRODUCT_UUID \
-H "Authorization: Bearer YOUR_API_KEY"
```
## Stores via API
### List Connected Stores
```bash theme={null}
curl https://api.supapost.so/stores \
-H "Authorization: Bearer YOUR_API_KEY"
```
### Sync a Store
```bash theme={null}
curl -X POST https://api.supapost.so/stores/STORE_UUID/sync \
-H "Authorization: Bearer YOUR_API_KEY"
```
### Disconnect a Store
```bash theme={null}
curl -X DELETE https://api.supapost.so/stores/STORE_UUID \
-H "Authorization: Bearer YOUR_API_KEY"
```
Disconnecting a store removes all synced products from Supapost. This does not affect your actual e-commerce store.
# Publishing
Source: https://developers.supapost.so/guides/publishing
Publish content to social media platforms.
## Overview
Supapost supports publishing slideshows directly to connected social media accounts.
## Supported Platforms
| Platform | Status | Post Type |
| --------- | ----------- | ----------------------- |
| TikTok | Available | Photo slideshow (draft) |
| Instagram | Coming soon | — |
## Connecting Accounts
1. Go to **Settings > Social Accounts**
2. Click **Connect TikTok**
3. Authorize Supapost in the TikTok OAuth flow
4. Your account appears in the publish dropdown
## Publishing from the Editor
1. Open your slides in the editor
2. Click the **dropdown arrow** next to Export
3. Under **Publish to**, select your account
4. Slides are exported, uploaded, and sent to TikTok
Currently, TikTok posts are created as **drafts** in your TikTok account with `SELF_ONLY` privacy. You can review and publish them from the TikTok app.
## Publishing via API
```bash theme={null}
curl -X POST https://api.supapost.so/publish/tiktok \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": "account-uuid",
"image_urls": [
"https://cdn.supapost.so/exports/slide-1.jpg",
"https://cdn.supapost.so/exports/slide-2.jpg"
],
"title": "My slideshow"
}'
```
## Image Requirements
* Format: **JPEG** or **WebP** (PNG is not supported by TikTok)
* Recommended size: **1080x1920** (9:16)
* Images must be publicly accessible URLs
# Scheduling
Source: https://developers.supapost.so/guides/scheduling
Schedule posts for automatic publishing.
## Overview
Schedule your slideshows to publish automatically at a specific date and time. A Cloudflare Workers cron job checks every minute for due posts and publishes them.
## Scheduling from the Editor
1. Create your slides in **Studio > Slides**
2. Click the **dropdown arrow** next to Export
3. Under **Schedule**, select your connected account
4. Pick a date and time
5. Click **Schedule**
The slides are exported, uploaded to R2, and a scheduled post is created.
## Scheduling via API
```bash theme={null}
curl -X POST https://api.supapost.so/schedule/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"social_account_id": "account-uuid",
"platform": "tiktok",
"scheduled_at": "2026-04-10T14:00:00Z",
"title": "Morning routine tips",
"image_urls": [
"https://cdn.supapost.so/exports/slide-1.jpg",
"https://cdn.supapost.so/exports/slide-2.jpg"
]
}'
```
## Post Statuses
| Status | Description |
| ------------ | ----------------------------------------------------- |
| `scheduled` | Waiting to be published at the scheduled time |
| `publishing` | Currently being published (in progress) |
| `published` | Successfully published to the platform |
| `failed` | Publishing failed — check `error_message` for details |
| `cancelled` | Manually cancelled by the user |
## Managing Scheduled Posts
```bash theme={null}
# List scheduled posts for a date range
curl "https://api.supapost.so/schedule/posts?from=2026-04-07&to=2026-04-14" \
-H "Authorization: Bearer YOUR_API_KEY"
# Reschedule a post
curl -X PATCH https://api.supapost.so/schedule/posts/POST_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"scheduled_at": "2026-04-11T16:00:00Z"}'
# Cancel a post
curl -X PATCH https://api.supapost.so/schedule/posts/POST_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "cancelled"}'
```
# Slides
Source: https://developers.supapost.so/guides/slides
Create AI-powered TikTok slideshows.
## Overview
Supapost's slide system lets you create TikTok-ready slideshows either manually through the visual editor or automatically with AI.
## AI Generation
Send a text prompt and the AI agent will:
1. Create slides with gradient backgrounds
2. Generate AI images for each slide background (via FAL FLUX)
3. Add text layers with proper positioning and styling
```bash theme={null}
curl -X POST https://api.supapost.so/generate/slides \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "5 slides about productivity tips, minimal style"}'
```
## Canvas Dimensions
All slides use a **1080 x 1920px** canvas (9:16 portrait), optimized for TikTok and Instagram Reels.
## Export
Slides can be exported as:
* **JPEG** — For publishing to social media
* **PNG** — For download and manual use
The export system renders each slide to a canvas element, including all layers (text, images, shapes, drawings), and uploads the result to R2 storage.
# Introduction
Source: https://developers.supapost.so/introduction
Supapost is an AI-powered social media content creation and scheduling platform.
## What is Supapost?
Supapost helps you create, schedule, and publish social media content — specifically TikTok slideshows — using AI-powered tools.
### Key Features
* **AI Slide Generation** — Describe your content and an AI agent creates complete slideshows with backgrounds, text, and images
* **Visual Slide Editor** — Full-featured canvas editor with layers, shapes, text, drawing tools, and image support
* **AI Influencer Studio** — Create consistent AI-generated personas for your content
* **Scheduling** — Schedule posts to publish automatically at optimal times
* **Multi-Platform Publishing** — Publish directly to TikTok (Instagram coming soon)
* **API Access** — Full REST API with API key authentication for programmatic access
### Architecture
Supapost is built with:
* **Frontend** — Next.js with shadcn/ui components
* **API** — Hono on Cloudflare Workers
* **Database** — Supabase (PostgreSQL) with Row Level Security
* **Storage** — Cloudflare R2 for media assets
* **AI** — Anthropic Claude for slide generation, FAL for image generation
* **Auth** — Supabase Auth with Google OAuth
### Getting Started
Get up and running in 5 minutes
Explore the REST API
# Quickstart
Source: https://developers.supapost.so/quickstart
Get started with the Supapost API in under 5 minutes.
## 1. Get your API key
Navigate to **Settings > Developer** in the Supapost dashboard and create a new API key.
## 2. Make your first request
```bash theme={null}
curl -X POST https://api.supapost.so/generate/slides \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Create 3 slides about morning routines with motivational text"
}'
```
## 3. Check the response
The API returns slide definitions with backgrounds, text layers, and AI-generated images:
```json theme={null}
{
"slides": [
{
"name": "Slide 1",
"background": {
"type": "image",
"imageUrl": "https://cdn.supapost.so/exports/..."
}
}
],
"texts": [
{
"slide_index": 0,
"text": {
"content": "Transform Your Mornings",
"fontSize": 84,
"fontWeight": 800,
"x": 90,
"y": 750,
"width": 900,
"color": "#ffffff",
"textAlign": "center"
}
}
],
"images": [
{
"slide_index": 0,
"image_url": "https://cdn.supapost.so/exports/..."
}
]
}
```
## Next steps
* [Authentication](/authentication) — Learn about API key and JWT auth
* [Generate slides](/api-reference/generate-slides) — Full API reference
* [Scheduling](/guides/scheduling) — Schedule posts for auto-publishing