# 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