### GET /api/settings/profile Source: https://www.fuxux.com/openapi.json API endpoint for GET /api/settings/profile ```markdown ### Responses #### 200 - OK **ProfileResponse** - **id** (string (uuid)) - **email** (string (email)) - **full_name** (string) - **plan** (string (free|creator|growth|pro)) ("free"|"creator"|"growth"|"pro") - **created_at** (string) - **onboarding_completed** (boolean) - **onboarding_step** (integer) - **email_verified_at** (string (date-time)) - **email_confirmed** (boolean): Whether the account's email address has completed Supabase Auth confirmation. - **has_api_access** (boolean): Whether the plan includes the API access add-on. An API key on an account without the add-on is rejected with 401, the same answer as a wrong key. - **subscription_status** (string): Live Stripe subscription status (e.g. `trialing`, `active`, `canceled`), or `null` if there is no subscription. - **trial_end** (string (date-time)): End of the Stripe trial period, or `null` if not currently trialing. #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X GET "https://www.fuxux.com/api/settings/profile" ``` ``` -------------------------------- ### API Overview: Fuxux API Source: https://www.fuxux.com/openapi.json Schedule and publish to 14 social platforms, manage connected accounts, upload media, and generate AI captions from your own apps, agents, or CI pipelines. Every endpoint below mirrors something you can do in the Fuxux dashboard. ## Access The API is part of the **API add-on** ($5/month on any paid plan: Creator, Growth or Pro). API keys aren't available on the Free plan. ## Authentication Send your **personal API key** on every authenticated request: `Authorization: Bearer fx_live_…` Create keys on the **API keys** page of the dashboard. The full secret is shown **only once** when you create or rotate a key; store it in an environment variable. You can have up to **10 active keys** and create or rotate up to **20 a day**. Use one key per integration: rotating a key revokes the old one, so a shared key breaks every client that uses it. `GET /api/settings/profile` is the recommended connection test: it's cheap and has no side effects. A key on an account without the API add-on is refused with 401, like a wrong key. ## Posting `POST /api/posts` publishes immediately, schedules with `scheduled_at`, or saves a draft with `draft: true`. Send `scheduled_at` with `Z` or an offset (`2027-01-15T09:30:00-08:00`): a time without one is read as UTC, not as the account's time zone. `captions` maps each platform id to its caption. Add `targets` to choose exact accounts and per-platform options; it is how you pick between several accounts on one platform. Platform ids: `twitter`, `instagram`, `linkedin`, `facebook`, `tiktok`, `youtube`, `bluesky`, `threads`, `pinterest`, `discord`, `kick`, `twitch`. Reddit isn't supported. Google Business Profile is coming soon and can't be connected or posted to yet. Each platform's own rules still apply (for example, Instagram and TikTok need media). Connect accounts in Fuxux first, then list them with `GET /api/accounts`. ## Rate limits and polling **120 requests/min per key** and **300/min per account** across all keys; creating posts is limited to **30 per 5 minutes**. Over a limit you get **429** with `Retry-After` (seconds) — wait that long. Don't poll: publishing settles on the order of minutes, so check a post's status at most once a minute (or use a webhook). ## Webhooks Set a webhook URL on the API keys page to receive a `post.finished` event when a post's publishing completes. Its `status` is `published` when at least one platform succeeded, so read the per-platform results too. A delivery is tried once. Each delivery is signed: `X-Fuxux-Signature: sha256=` is the HMAC-SHA256 of the raw body with your webhook secret. ## Errors Standard HTTP status codes with JSON `{ "error": "…" }` bodies: - **400** — validation, including a platform rule (such as Instagram needing media), no connected account for any captioned platform (without `targets`, platforms with no account are skipped: compare `results` with your captions), or editing a post that is not a draft or scheduled - **401** — missing, invalid or revoked key, or the API add-on isn't active - **403** — see `code`: `post_quota_reached` (the plan's post allowance is used up), `x_allowance` (the month's X allowance is used up) or `reddit_web_only` (Reddit can only be posted to from the web app) - **404** — the post doesn't exist in your workspace - **409** — the post started publishing during your request, or a delete was sent while it is publishing - **429** — rate limited; honor `Retry-After` Rotate any key that is ever exposed. ## Other ways in Prefer not to write HTTP yourself? The [MCP server](/mcp/docs) connects Claude Code, Claude Desktop, Cursor and [Manus/Cue](/cue); the [agent skill](/agent-skill) packages the API for OpenClaw; [Zapier](/zapier) connects without code; the [WordPress plugin](/platforms/wordpress) cross-posts when you publish; and the [browser extensions](/extensions) share any page to your accounts. ```yaml # Fuxux API # Version: 1.1.0 Schedule and publish to 14 social platforms, manage connected accounts, upload media, and generate AI captions from your own apps, agents, or CI pipelines. Every endpoint below mirrors something you can do in the Fuxux dashboard. ## Access The API is part of the **API add-on** ($5/month on any paid plan: Creator, Growth or Pro). API keys aren't available on the Free plan. ## Authentication Send your **personal API key** on every authenticated request: `Authorization: Bearer fx_live_…` Create keys on the **API keys** page of the dashboard. The full secret is shown **only once** when you create or rotate a key; store it in an environment variable. You can have up to **10 active keys** and create or rotate up to **20 a day**. Use one key per integration: rotating a key revokes the old one, so a shared key breaks every client that uses it. `GET /api/settings/profile` is the recommended connection test: it's cheap and has no side effects. A key on an account without the API add-on is refused with 401, like a wrong key. ## Posting `POST /api/posts` publishes immediately, schedules with `scheduled_at`, or saves a draft with `draft: true`. Send `scheduled_at` with `Z` or an offset (`2027-01-15T09:30:00-08:00`): a time without one is read as UTC, not as the account's time zone. `captions` maps each platform id to its caption. Add `targets` to choose exact accounts and per-platform options; it is how you pick between several accounts on one platform. Platform ids: `twitter`, `instagram`, `linkedin`, `facebook`, `tiktok`, `youtube`, `bluesky`, `threads`, `pinterest`, `discord`, `kick`, `twitch`. Reddit isn't supported. Google Business Profile is coming soon and can't be connected or posted to yet. Each platform's own rules still apply (for example, Instagram and TikTok need media). Connect accounts in Fuxux first, then list them with `GET /api/accounts`. ## Rate limits and polling **120 requests/min per key** and **300/min per account** across all keys; creating posts is limited to **30 per 5 minutes**. Over a limit you get **429** with `Retry-After` (seconds) — wait that long. Don't poll: publishing settles on the order of minutes, so check a post's status at most once a minute (or use a webhook). ## Webhooks Set a webhook URL on the API keys page to receive a `post.finished` event when a post's publishing completes. Its `status` is `published` when at least one platform succeeded, so read the per-platform results too. A delivery is tried once. Each delivery is signed: `X-Fuxux-Signature: sha256=` is the HMAC-SHA256 of the raw body with your webhook secret. ## Errors Standard HTTP status codes with JSON `{ "error": "…" }` bodies: - **400** — validation, including a platform rule (such as Instagram needing media), no connected account for any captioned platform (without `targets`, platforms with no account are skipped: compare `results` with your captions), or editing a post that is not a draft or scheduled - **401** — missing, invalid or revoked key, or the API add-on isn't active - **403** — see `code`: `post_quota_reached` (the plan's post allowance is used up), `x_allowance` (the month's X allowance is used up) or `reddit_web_only` (Reddit can only be posted to from the web app) - **404** — the post doesn't exist in your workspace - **409** — the post started publishing during your request, or a delete was sent while it is publishing - **429** — rate limited; honor `Retry-After` Rotate any key that is ever exposed. ## Other ways in Prefer not to write HTTP yourself? The [MCP server](/mcp/docs) connects Claude Code, Claude Desktop, Cursor and [Manus/Cue](/cue); the [agent skill](/agent-skill) packages the API for OpenClaw; [Zapier](/zapier) connects without code; the [WordPress plugin](/platforms/wordpress) cross-posts when you publish; and the [browser extensions](/extensions) share any page to your accounts. # Base URL: https://www.fuxux.com ``` -------------------------------- ### GET /api/usage Source: https://www.fuxux.com/openapi.json Returns the current plan, active workspace, and usage counters for account and AI limits. ```markdown ### Responses #### 200 - OK **UsageResponse** - **plan** (string (free|creator|growth|pro)) ("free"|"creator"|"growth"|"pro") - **limits** (object) - **accounts** (integer): -1 means unlimited. - **aiPerMonth** (integer) - **postsPerMonth** (integer): Published posts allowed per month on the plan of the space's owner; null when unlimited. - **xUnitsPerMonth** (integer): Monthly allowance for publishing to X. 0 means X is not included in the plan. A post is 1 unit, a post with a link 13. - **usage** (object) - **accounts** (integer) - **aiThisMonth** (integer) - **postsThisMonth** (integer) - **xUnitsThisMonth** (integer) #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X GET "https://www.fuxux.com/api/usage" ``` ``` -------------------------------- ### GET /api/dashboard Source: https://www.fuxux.com/openapi.json Profile name, stats, next scheduled posts, and per-platform connection snapshot. ```markdown ### Responses #### 200 - OK **DashboardResponse** - **profile** (object) - **full_name** (string) - **stats** (object) - **postsThisMonth** (integer) - **postsLastMonth** (integer) - **momChange** (integer): Month-over-month % change; null if no prior month data - **totalPublished** (integer) - **upcomingThisWeek** (integer) - **connectedAccounts** (integer) - **upcomingPosts** (array (object)) Array items: - **id** (string (uuid)) - **scheduled_at** (string (date-time)) - **status** (string) - **raw_prompt** (string) - **post_variants** (array (object)) Array items: - **platform** (string) - **content** (string) - **platforms** (array (object)) Array items: - **id** (string) - **name** (string) - **icon** (string) - **connected** (boolean) - **posts** (integer) - **username** (string) #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 429 - Too many requests Too many requests ### Example Usage ```bash curl -X GET "https://www.fuxux.com/api/dashboard" ``` ``` -------------------------------- ### GET /api/posts Source: https://www.fuxux.com/openapi.json API endpoint for GET /api/posts ```markdown ### Parameters - **month** (string, query, optional): When set, returns posts scheduled in that calendar month, plus posts published immediately (no `scheduled_at`) in that month. Boundaries are widened by 14 hours each side so local-time edge days aren't dropped. (example: "2026-04") - **status** (string (scheduled|published|draft|failed|has_failed|all), query, optional): Filter by post status; omit or `all` for no status filter. `has_failed` returns every post where at least one platform failed, including posts that published on other platforms (their status reads `published`); `post_variants` still lists every platform's result. Combine with `order=updated_at_desc` to poll for new failures. - **limit** (integer, query, optional): Max posts to return, clamped to 1-50 (a non-numeric value means 20). If omitted: 50, or the whole month (up to 999 posts) when `month` is set. `hasMore` and `nextOffset` in the response tell you whether another page exists. - **offset** (integer, query, optional): Number of posts to skip for pagination, paired with `limit`. Non-numeric or negative values are treated as 0. - **order** (string (published_at_desc|created_at_desc|updated_at_desc), query, optional): Optional sort order. `published_at_desc` returns the most recently published posts first (unpublished posts last); `created_at_desc` the most recently created first; `updated_at_desc` the most recently changed first (useful for catching failures on older posts). Omit for the default order (soonest scheduled first). - **include** (string (updated_at), query, optional): Optional. `updated_at` adds each post's `updated_at` to the response: the time the post last changed, which moves when it is published or fails. Pair it with `order=updated_at_desc` when polling for failures. ### Responses #### 200 - OK **PostsListResponse** - **posts** (array (PostRow)) Array items: - **id** (string (uuid)) - **status** (string (draft|scheduled|publishing|published|failed)) ("draft"|"scheduled"|"publishing"|"published"|"failed") - **raw_prompt** (string) - **scheduled_at** (string (date-time)) - **published_at** (string (date-time)) - **created_at** (string (date-time)) - **updated_at** (string (date-time)): When the post last changed. Only present on GET /api/posts when `include=updated_at` is sent. - **post_variants** (array (PostVariant)) Array items: - **id** (string (uuid)) - **platform** (string) - **content** (string) - **status** (string) - **error_message** (string) - **platform_post_id** (string) - **published_at** (string (date-time)) - **hasMore** (boolean): Whether another page exists. - **nextOffset** (integer): The `offset` to send for the next page. - **counts** (object) - **total** (integer) - **scheduled** (integer) - **published** (integer) - **drafts** (integer) - **failed** (integer) #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 429 - Too many requests Too many requests #### 500 - Server error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X GET "https://www.fuxux.com/api/posts?month=2026-04&status=scheduled&limit=0&offset=0&order=published_at_desc&include=updated_at" ``` ``` -------------------------------- ### GET /api/accounts Source: https://www.fuxux.com/openapi.json API endpoint for GET /api/accounts ```markdown ### Responses #### 200 - OK - **accounts** (array (object)) (required) Array items: - **id** (string (uuid)) - **platform** (string) - **platform_username** (string) - **platform_avatar_url** (string) - **token_expires_at** (string (date-time)) - **created_at** (string (date-time)) - **status** (string (connected|expired)): "expired" means the account must be reconnected in the Fuxux dashboard before it can publish again. ("connected"|"expired") #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 429 - Too many requests Too many requests #### 500 - Server error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X GET "https://www.fuxux.com/api/accounts" ``` ``` -------------------------------- ### GET /api/analytics Source: https://www.fuxux.com/openapi.json API endpoint for GET /api/analytics ```markdown ### Parameters - **days** (integer, query, optional): Sliding window length for chart and breakdown; invalid values default to 30. ### Responses #### 200 - OK **AnalyticsResponse** - **chartDays** (integer) ("7"|"14"|"30"|"90") - **summary** (object) - **totalPublished** (integer) - **publishedThisMonth** (integer) - **publishedLastMonth** (integer) - **momChange** (integer) - **scheduled** (integer) - **successRate** (number): % of variants published successfully in the selected window - **dailyPosts** (array (object)) Array items: - **date** (string): YYYY-MM-DD - **count** (integer) - **platformBreakdown** (array (object)) Array items: - **platform** (string) - **name** (string) - **icon** (string) - **published** (integer) - **failed** (integer) - **engagement** (object) - **likes** (integer) - **comments** (integer) - **shares** (integer) - **views** (integer) - **impressions** (integer) - **reach** (integer) - **postsWithInsights** (integer): How many of this platform's published posts in the window have synced engagement data - **engagement** (object) - **recentPosts** (array (object)) #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X GET "https://www.fuxux.com/api/analytics?days=30" ``` ``` -------------------------------- ### GET /api/posts/{id} Source: https://www.fuxux.com/openapi.json One post with its per-platform variants, including drafts (which the month-scoped list can miss). Variant ids are what PATCH `variant_updates` uses. ```markdown ### Parameters - **id** (string (uuid), path, required) ### Responses #### 200 - OK - **post** (object) (required) - **id** (string (uuid)) - **status** (string (draft|scheduled|publishing|published|failed)) ("draft"|"scheduled"|"publishing"|"published"|"failed") - **raw_prompt** (string) - **scheduled_at** (string (date-time)) - **published_at** (string (date-time)) - **created_at** (string (date-time)) - **updated_at** (string (date-time)): When the post last changed. Only present on GET /api/posts when `include=updated_at` is sent. - **post_variants** (array (PostVariant)) Array items: - **id** (string (uuid)) - **platform** (string) - **content** (string) - **status** (string) - **error_message** (string) - **platform_post_id** (string) - **published_at** (string (date-time)) #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 404 - Post not found **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X GET "https://www.fuxux.com/api/posts/{id}" ``` ``` -------------------------------- ### Schema: PostCreate Source: https://www.fuxux.com/openapi.json `captions` is required unless `draft` is `true`, in which case `prompt` or at least one caption must be present instead. ```markdown ## Schema: PostCreate `captions` is required unless `draft` is `true`, in which case `prompt` or at least one caption must be present instead. **Type:** object - **prompt** (string): Optional idea stored on the post - **captions** (object) (required): Map of platform id → caption. Platform ids: `twitter`, `instagram`, `linkedin`, `facebook`, `tiktok`, `youtube`, `bluesky`, `threads`, `pinterest`, `discord`, `kick`, `twitch`, `telegram`, `slack`. Unknown platform keys are ignored. Without `targets`, each captioned platform posts to its first connected account. Reddit is not available through the API: Reddit posts are created in the Fuxux web app, and a `reddit` caption or target is refused with 403 `reddit_web_only`. Google Business Profile is coming soon and can't be connected or posted to yet. - **targets** (array (PostTarget)): Optional: exactly which connected accounts to post to, with per-platform options. Each target needs a caption for its platform in `captions`. Needed for picking between several accounts on one platform. Array items: - **account_id** (string (uuid)) (required): Connected account id from `GET /api/accounts` - **platform** (string (twitter|instagram|linkedin|facebook|tiktok|youtube|bluesky|threads|pinterest|discord|kick|twitch|telegram|slack)) (required): Must match the account's platform ("twitter"|"instagram"|"linkedin"|"facebook"|"tiktok"|"youtube"|"bluesky"|"threads"|"pinterest"|"discord"|"kick"|"twitch"|"telegram"|"slack") - **format** (string (feed|story)): Instagram and Facebook only; defaults to `feed` ("feed"|"story") - **boardId** (string): Pinterest only: id of the board to pin to. If omitted, the pin goes to the account's first public board. - **tiktokOptions** (object): TikTok only. `mode` `inbox` (default) sends the video to the creator's TikTok inbox to finish; `direct` publishes it (needs Direct Post access on the account). - **mode** (string (inbox|direct)) ("inbox"|"direct") - **privacyLevel** (string): One of the privacy levels TikTok offers the account (for example `SELF_ONLY`) - **disableComment** (boolean) - **disableDuet** (boolean) - **disableStitch** (boolean) - **brandOrganic** (boolean): Promotional content (your own brand) - **brandContent** (boolean): Paid partnership (branded content); can't be private - **category** (object): Twitch and Kick only: stream category set with the title (Twitch game id or Kick category id) - **id** (string) (required) - **name** (string) (required) - **scheduled_at** (string (date-time)): If set, post is scheduled (must be in the future). If omitted, the app publishes immediately. Mutually exclusive with `draft`. - **media_urls** (array (string (uri))): Public URLs from `POST /api/media/upload` - **draft** (boolean): If `true`, saves the post as a draft instead of scheduling or publishing it. `captions` is not required when `draft` is `true`, but `prompt` or at least one caption must be present. Mutually exclusive with `scheduled_at`. ``` -------------------------------- ### POST /api/media/upload Source: https://www.fuxux.com/openapi.json Multipart form field `file`. Fuxux allows up to **50 MB**, but the hosting platform hard-caps any single request body at **~4.5 MB** — larger files fail here regardless of the 50 MB limit; host them yourself and pass a public HTTPS URL in `media_urls` instead. Allowed types: JPEG, PNG, GIF, WebP, MP4, MOV, WebM. ```markdown ### Request Body **Content-Type:** multipart/form-data - **file** (string (binary)) (required) ### Responses #### 200 - Public URL - **url** (string (uri)) (required) - **path** (string) (required) #### 400 - Missing file or disallowed type/size **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 500 - Upload failed **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X POST "https://www.fuxux.com/api/media/upload" \ -H "Content-Type: application/json" \ -d '{ "file": "string" }' ``` ``` -------------------------------- ### POST /api/tools/youtube-tags Source: https://www.fuxux.com/openapi.json No authentication. Rate limited per IP (per hour). ```markdown ### Request Body **Content-Type:** application/json - **topic** (string) (required): Video topic / title / description ### Responses #### 200 - Tag list - **tags** (array (string)) (required) #### 400 - Validation error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 429 - Too many requests Too many requests #### 502 - Generation or parse error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 503 - Service unavailable **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X POST "https://www.fuxux.com/api/tools/youtube-tags" \ -H "Content-Type: application/json" \ -d '{ "topic": "string" }' ``` ``` -------------------------------- ### POST /api/ai/generate Source: https://www.fuxux.com/openapi.json Enforces the plan's AI limits: a monthly number on Free, and fair-use limits per day and per month on paid plans. When a limit is reached the response is **429** with `code: "ai_limit"` and an `ai_limit` object (`reason`, `used`, `limit`, `resetsAt`). Valid platform ids: `twitter`, `instagram`, `linkedin`, `facebook`, `tiktok`, `youtube`, `bluesky`, `threads`, `pinterest`, `discord`, `twitch`, `kick`, `telegram`, `slack`, `google-business`. Reddit is not available here. Ids that are not recognised are ignored; repeated ids count once. ```markdown ### Request Body **Content-Type:** application/json - **prompt** (string) (required) - **platforms** (array (string)) (required): Platforms to generate in one call - **regenerate** (string): If set, only this platform id is regenerated; `platforms` is ignored for selection. ### Responses #### 200 - OK **AiCaptionsResponse** - **captions** (object): Platform id → generated caption #### 400 - Validation error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 429 - User rate limit or monthly AI cap **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 500 - Misconfiguration **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 502 - Upstream model error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X POST "https://www.fuxux.com/api/ai/generate" \ -H "Content-Type: application/json" \ -d '{ "prompt": "string", "platforms": [ "string" ], "regenerate": "string" }' ``` ``` -------------------------------- ### Schema: UsageResponse Source: https://www.fuxux.com/openapi.json Schema definition for UsageResponse ```markdown ## Schema: UsageResponse Schema definition for UsageResponse **Type:** object - **plan** (string (free|creator|growth|pro)) ("free"|"creator"|"growth"|"pro") - **limits** (object) - **accounts** (integer): -1 means unlimited. - **aiPerMonth** (integer) - **postsPerMonth** (integer): Published posts allowed per month on the plan of the space's owner; null when unlimited. - **xUnitsPerMonth** (integer): Monthly allowance for publishing to X. 0 means X is not included in the plan. A post is 1 unit, a post with a link 13. - **usage** (object) - **accounts** (integer) - **aiThisMonth** (integer) - **postsThisMonth** (integer) - **xUnitsThisMonth** (integer) ``` -------------------------------- ### Schema: PostTarget Source: https://www.fuxux.com/openapi.json Schema definition for PostTarget ```markdown ## Schema: PostTarget Schema definition for PostTarget **Type:** object - **account_id** (string (uuid)) (required): Connected account id from `GET /api/accounts` - **platform** (string (twitter|instagram|linkedin|facebook|tiktok|youtube|bluesky|threads|pinterest|discord|kick|twitch|telegram|slack)) (required): Must match the account's platform ("twitter"|"instagram"|"linkedin"|"facebook"|"tiktok"|"youtube"|"bluesky"|"threads"|"pinterest"|"discord"|"kick"|"twitch"|"telegram"|"slack") - **format** (string (feed|story)): Instagram and Facebook only; defaults to `feed` ("feed"|"story") - **boardId** (string): Pinterest only: id of the board to pin to. If omitted, the pin goes to the account's first public board. - **tiktokOptions** (object): TikTok only. `mode` `inbox` (default) sends the video to the creator's TikTok inbox to finish; `direct` publishes it (needs Direct Post access on the account). - **mode** (string (inbox|direct)) ("inbox"|"direct") - **privacyLevel** (string): One of the privacy levels TikTok offers the account (for example `SELF_ONLY`) - **disableComment** (boolean) - **disableDuet** (boolean) - **disableStitch** (boolean) - **brandOrganic** (boolean): Promotional content (your own brand) - **brandContent** (boolean): Paid partnership (branded content); can't be private - **category** (object): Twitch and Kick only: stream category set with the title (Twitch game id or Kick category id) - **id** (string) (required) - **name** (string) (required) ``` -------------------------------- ### Schema: ProfileResponse Source: https://www.fuxux.com/openapi.json Schema definition for ProfileResponse ```markdown ## Schema: ProfileResponse Schema definition for ProfileResponse **Type:** object - **id** (string (uuid)) - **email** (string (email)) - **full_name** (string) - **plan** (string (free|creator|growth|pro)) ("free"|"creator"|"growth"|"pro") - **created_at** (string) - **onboarding_completed** (boolean) - **onboarding_step** (integer) - **email_verified_at** (string (date-time)) - **email_confirmed** (boolean): Whether the account's email address has completed Supabase Auth confirmation. - **has_api_access** (boolean): Whether the plan includes the API access add-on. An API key on an account without the add-on is rejected with 401, the same answer as a wrong key. - **subscription_status** (string): Live Stripe subscription status (e.g. `trialing`, `active`, `canceled`), or `null` if there is no subscription. - **trial_end** (string (date-time)): End of the Stripe trial period, or `null` if not currently trialing. ``` -------------------------------- ### POST /api/posts Source: https://www.fuxux.com/openapi.json If `draft` is `true`, the post is stored with status `draft` and nothing is scheduled or published. Otherwise, if `scheduled_at` is set, variants are stored as scheduled and returned without publishing. If neither is set, the server attempts immediate publish to each platform in `captions`. ```markdown ### Parameters - **Idempotency-Key** (string, header, optional): Optional. Any unique string (1-255 visible ASCII characters, e.g. a UUID) chosen by the client for this one post. If the same request is sent again with the same key within 24 hours (after a timeout, say), no second post is created: the post from the first request is returned with status 200, the header `Idempotent-Replayed: true` and `idempotent_replay: true`. While the first request is still publishing, a repeat gets 409. The key is per user; reusing it with a different body gets 422. A request that was refused (4xx) does not use up its key. ### Request Body **Content-Type:** application/json - **prompt** (string): Optional idea stored on the post - **captions** (object) (required): Map of platform id → caption. Platform ids: `twitter`, `instagram`, `linkedin`, `facebook`, `tiktok`, `youtube`, `bluesky`, `threads`, `pinterest`, `discord`, `kick`, `twitch`, `telegram`, `slack`. Unknown platform keys are ignored. Without `targets`, each captioned platform posts to its first connected account. Reddit is not available through the API: Reddit posts are created in the Fuxux web app, and a `reddit` caption or target is refused with 403 `reddit_web_only`. Google Business Profile is coming soon and can't be connected or posted to yet. - **targets** (array (PostTarget)): Optional: exactly which connected accounts to post to, with per-platform options. Each target needs a caption for its platform in `captions`. Needed for picking between several accounts on one platform. Array items: - **account_id** (string (uuid)) (required): Connected account id from `GET /api/accounts` - **platform** (string (twitter|instagram|linkedin|facebook|tiktok|youtube|bluesky|threads|pinterest|discord|kick|twitch|telegram|slack)) (required): Must match the account's platform ("twitter"|"instagram"|"linkedin"|"facebook"|"tiktok"|"youtube"|"bluesky"|"threads"|"pinterest"|"discord"|"kick"|"twitch"|"telegram"|"slack") - **format** (string (feed|story)): Instagram and Facebook only; defaults to `feed` ("feed"|"story") - **boardId** (string): Pinterest only: id of the board to pin to. If omitted, the pin goes to the account's first public board. - **tiktokOptions** (object): TikTok only. `mode` `inbox` (default) sends the video to the creator's TikTok inbox to finish; `direct` publishes it (needs Direct Post access on the account). - **mode** (string (inbox|direct)) ("inbox"|"direct") - **privacyLevel** (string): One of the privacy levels TikTok offers the account (for example `SELF_ONLY`) - **disableComment** (boolean) - **disableDuet** (boolean) - **disableStitch** (boolean) - **brandOrganic** (boolean): Promotional content (your own brand) - **brandContent** (boolean): Paid partnership (branded content); can't be private - **category** (object): Twitch and Kick only: stream category set with the title (Twitch game id or Kick category id) - **id** (string) (required) - **name** (string) (required) - **scheduled_at** (string (date-time)): If set, post is scheduled (must be in the future). If omitted, the app publishes immediately. Mutually exclusive with `draft`. - **media_urls** (array (string (uri))): Public URLs from `POST /api/media/upload` - **draft** (boolean): If `true`, saves the post as a draft instead of scheduling or publishing it. `captions` is not required when `draft` is `true`, but `prompt` or at least one caption must be present. Mutually exclusive with `scheduled_at`. ### Responses #### 200 - Draft saved, scheduled post, or publish outcome - **post** (object) (required) - **id** (string (uuid)) (required) - **status** (string) (required) #### 400 - Validation error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 401 - Unauthorized **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 403 - Refused; nothing was created. See `code`: `post_quota_reached` (the plan's post allowance for this month would be exceeded), `x_allowance` (the month's X allowance is used up) or `reddit_web_only` (Reddit can only be posted to from the web app). **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 409 - Same `Idempotency-Key` as a request that is still publishing its post. Try again shortly; the post is not created twice. **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 422 - This `Idempotency-Key` was already used with a different request body. **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. #### 429 - Too many requests Too many requests #### 500 - Server error **Error** - **error** (string) - **code** (string): Present on some refusals, for example `post_quota_reached`, `x_allowance`, `reddit_web_only`. ### Example Usage ```bash curl -X POST "https://www.fuxux.com/api/posts" \ -H "Content-Type: application/json" \ -d '{ "prompt": "string", "captions": "value", "targets": [ "value" ], "scheduled_at": "2023-01-01T00:00:00Z", "media_urls": [ "string" ], "draft": "true" }' ``` ``` -------------------------------- ### Schema: PostVariant Source: https://www.fuxux.com/openapi.json Schema definition for PostVariant ```markdown ## Schema: PostVariant Schema definition for PostVariant **Type:** object - **id** (string (uuid)) - **platform** (string) - **content** (string) - **status** (string) - **error_message** (string) - **platform_post_id** (string) - **published_at** (string (date-time)) ``` -------------------------------- ### Schema: PostRow Source: https://www.fuxux.com/openapi.json Schema definition for PostRow ```markdown ## Schema: PostRow Schema definition for PostRow **Type:** object - **id** (string (uuid)) - **status** (string (draft|scheduled|publishing|published|failed)) ("draft"|"scheduled"|"publishing"|"published"|"failed") - **raw_prompt** (string) - **scheduled_at** (string (date-time)) - **published_at** (string (date-time)) - **created_at** (string (date-time)) - **updated_at** (string (date-time)): When the post last changed. Only present on GET /api/posts when `include=updated_at` is sent. - **post_variants** (array (PostVariant)) Array items: - **id** (string (uuid)) - **platform** (string) - **content** (string) - **status** (string) - **error_message** (string) - **platform_post_id** (string) - **published_at** (string (date-time)) ``` -------------------------------- ### Schema: PublishResult Source: https://www.fuxux.com/openapi.json Schema definition for PublishResult ```markdown ## Schema: PublishResult Schema definition for PublishResult **Type:** object - **platform** (string) - **account_id** (string) - **account_label** (string): Display label for the account, e.g. "@brand". - **success** (boolean) - **platform_post_id** (string) - **error** (string) - **still_processing** (boolean): Some networks confirm publish status asynchronously. If true, `success` is false but the post was accepted and may still go live — check the post's status again shortly rather than treating this as a hard failure. - **inbox_pending** (boolean): The platform accepted the media into an inbox/draft flow (e.g. TikTok's video upload inbox) rather than publishing directly. Counted as success, but the post is not necessarily live yet — the creator may need to finish posting from within that platform's own app. ``` -------------------------------- ### Schema: AiCaptionsResponse Source: https://www.fuxux.com/openapi.json Schema definition for AiCaptionsResponse ```markdown ## Schema: AiCaptionsResponse Schema definition for AiCaptionsResponse **Type:** object - **captions** (object): Platform id → generated caption ```